Используйте GetForegroundWindow () вместо GetDesktopWindow ().
Вам нужно сохранить дескриптор, возвращаемый GetForegroundWindow () и передать сохраненное значение в ReleaseDC () - чтобы убедиться, что GetWindowDC () и ReleaseDC () называются точно для одного и того же окна, если активное окно изменяется между вызовами.
В теории они будут использовать те же планы и выполнять почти то же время.
На практике,
SELECT TOP 1 Id FROM Table1 ORDER BY Id DESC
будет, более вероятно, использовать PRIMARY KEY INDEX
.
кроме того, этот является более растяжимым, если Вы решите еще выбрать некоторых столбец наряду с id
.
в фактическом плане по MAX()
говорится:
SELECT <- AGGREGATE <- TOP <- CLUSTERED INDEX SCAN
, в то время как в плане относительно TOP 1
говорится:
SELECT <- TOP <- CLUSTERED INDEX SCAN
, т.е. aggregate
опущен.
Агрегат на самом деле ничего не сделает здесь, поскольку существует всего лишь одна строка.
P. S. Как @Mehrdad Afshari
и @John Sansom
отмеченный, на неиндексируемом поле MAX
немного быстрее (конечно, не 20
времена, как оптимизатор говорит):
-- 18,874,368 rows SET LANGUAGE ENGLISH SET STATISTICS TIME ON SET STATISTICS IO ON PRINT 'MAX' SELECT MAX(id) FROM master PRINT 'TOP 1' SELECT TOP 1 id FROM master ORDER BY id DESC PRINT 'MAX' SELECT MAX(id) FROM master PRINT 'TOP 1' SELECT TOP 1 id FROM master ORDER BY id DESC PRINT 'MAX' SELECT MAX(id) FROM master PRINT 'TOP 1' SELECT TOP 1 id FROM master ORDER BY id DESC PRINT 'MAX' SELECT MAX(id) FROM master PRINT 'TOP 1' SELECT TOP 1 id FROM master ORDER BY id DESC PRINT 'MAX' SELECT MAX(id) FROM master PRINT 'TOP 1' SELECT TOP 1 id FROM master ORDER BY id DESC Changed language setting to us_english. SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. MAX SQL Server Execution Times: CPU time = 0 ms, elapsed time = 20 ms. (строк обработано: 1) Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 447, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 5452 ms, elapsed time = 2766 ms. TOP 1 SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. (строк обработано: 1) Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 2, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 6813 ms, elapsed time = 3449 ms. MAX SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. (строк обработано: 1) Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 44, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 5359 ms, elapsed time = 2714 ms. TOP 1 SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. (строк обработано: 1) Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 6766 ms, elapsed time = 3379 ms. MAX SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. (строк обработано: 1) Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 5406 ms, elapsed time = 2726 ms. TOP 1 SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. (строк обработано: 1) Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 6780 ms, elapsed time = 3415 ms. MAX SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. (строк обработано: 1) Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 85, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 5392 ms, elapsed time = 2709 ms. TOP 1 SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. (строк обработано: 1) Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 10, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 6766 ms, elapsed time = 3387 ms. MAX SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. (строк обработано: 1) Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 5374 ms, elapsed time = 2708 ms. TOP 1 SQL Server Execution Times: CPU time = 0 ms, elapsed time = 1 ms. (строк обработано: 1) Table 'master'. Scan count 3, logical reads 32655, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. SQL Server Execution Times: CPU time = 6797 ms, elapsed time = 3494 ms.
, Если между двумя запросами существует кластерный индекс, нет фактически никакой разницы в производительности.
Это - becuase, оба выполнят Сканирование Кластерного индекса, которое перенесет 100% стоимости запроса.
Выполнение двух запросов на столбце, который не имеет индекса, приводит к 3 операторам, используемым в обоих планах выполнения.
Главный пункт использует оператор Sort, и функция Max использует Потоковый Агрегатный оператор.
, Когда нет никакого индекса, МАКС () функция обеспечивает лучшую производительность.
Подтверждение концепции может быть найдено, и полная пошаговая демонстрация сценария тестирования может быть найдена здесь
Просто сравните планы выполнения, и Вы будете видеть (нажмите Ctrl+M
in Management Studio при редактировании запроса). Мое произвольное предположение будет то, что эти запросы одинаково производительны, если существует (кластеризованный) индекс на Id
столбец.
Однако это в целом очень плохо идея.
Я только что протестировал эти два SQL-оператора, Вы приняли меры против типичного набора данных:
SELECT MAX(Id) FROM Table1
SELECT TOP 1 Id FROM Table1 ORDER BY Id DESC
И SELECT TOP 1 Id FROM Table1 ORDER BY Id DESC
незначительно быстрее, потому что это имеет один последний шаг в плане выполнения. Вот планы выполнения, которые выполняет каждый запрос:
ВЫБОР МАКС (идентификатор) ОТ Сканирования кластерного индекса Table1
>> Вершина>> Потоковый Агрегат>> Выбор
ИЗБРАННЫЙ идентификатор TOP 1 ОТ идентификационного Сканирования кластерного индекса DESC
ORDER BY Table1>> Вершина>> Выбор
MAX
обычно быстрее.
Оба запроса будут использовать индекс на столбце, если будет существовать.
, Если никакой индекс не существует на столбце, эти TOP 1
, запрос будет использовать Top N Sort
оператор к [1 112] вид таблица вместо [1 113] потоковое агрегирование , который делает его медленнее.
MAX
также обеспечивает лучшую удобочитаемость.
Примечание Стороны: в то время как MAX
будет использовать потоковый агрегатный оператор в плане выполнения в индексируемом случае, он не имеет никакой определенной стоимости, поскольку он просто обрабатывает одну строку (Actual Rows = 1
). Можно сравнить запросы путем выполнения их в едином пакете и видеть относительную стоимость. В индексируемом случае оба запроса будут стоить 50%. Я протестировал неиндексируемый случай на таблице приблизительно с 7 000 строк, и TOP будет стоить 65% по сравнению с МАКСОМ, который стоит 35%.
Да в этом идентификаторе случая поле, на котором я определил кластерный индекс. Если индекс является идентификатором DESC тогда что.. И да было бы хорошо знать, как производительность будет затронута, если
- идентификатор будет кластерным индексом + первичный ключ.
- идентификатор является кластерным индексом и не первичным ключом.
- идентификатор является не ASC кластерного индекса + первичный ключ.
- идентификатор является не ASC кластерного индекса и не первичным ключом.
- идентификатор является не кластерным индексом DESC + первичный ключ.
- идентификатор является не кластерным индексом DESC и не первичный ключ.
- идентификатор является просто AutoIncrement
Для Случаев 1 и 2, оба выполнят сканирование кластерного индекса, которое возвращает единственную запись. Нет никакого различия IO между двумя запросами.
Для Случаев 3, 4, 5 и 6, оба выполнят индексное сканирование, которое возвращает единственную запись. Нет никакого различия IO между двумя запросами.
Для Случая 7, оба выполнят сканирование таблицы. Нет никакой разницы в стоимости IO.
Сводка: Случай 1-6 сделан из победы! Если Вы - то, в случае, если 7, то Вы уже проиграли с точки зрения IO.
можно измерить IO при помощи Запроса SQL анализатор. Выполните это перед своим запросом.
SET STATISTICS IO ON
Никто не упомянул IDENT_CURRENT ('Table1') - их всех сдуло - конечно, это работает только с идентификационными столбцами, но был вопрос ...