У меня есть запрос, который работает намного быстрее с выбором top 100
и намного медленнее без top 100
. Количество возвращаемых записей равно 0. Не могли бы вы объяснить разницу в планах запросов или поделиться ссылками, где объясняется такая разница?
Запрос без top
текста:
SELECT --TOP 100
*
FROM InventTrans
JOIN
InventDim
ON InventDim.DATAAREAID = 'dat' AND
InventDim.INVENTDIMID = InventTrans.INVENTDIMID
WHERE InventTrans.DATAAREAID = 'dat' AND
InventTrans.ITEMID = '027743' AND
InventDim.INVENTLOCATIONID = 'КзРЦ Алмат' AND
InventDim.ECC_BUSINESSUNITID = 'Казахстан';
План запроса для вышеперечисленного (без top
):
Статистика IO и TIME (без top
):
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
(0 row(s) affected)
Table 'INVENTDIM'. Scan count 0, logical reads 988297, physical reads 0, read-ahead reads 1, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'INVENTTRANS'. Scan count 1, logical reads 1234560, physical reads 0, read-ahead reads 14299, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
SQL Server Execution Times:
CPU time = 6256 ms, elapsed time = 13348 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
Используемые индексы (без top
):
1. INVENTTRANS.I_177TRANSIDIDX
4 KEYS:
- DATAAREAID
- INVENTTRANSID
- INVENTDIMID
- RECID
2. INVENTTRANS.I_177ITEMIDX
3 KEYS:
- DATAAREAID
- ITEMID
- DATEPHYSICAL
3. INVENTDIM.I_698DIMIDIDX
2 KEYS:
- DATAAREAID
- INVENTDIMID
Запрос с top
:
SELECT TOP 100
*
FROM InventTrans
JOIN
InventDim
ON InventDim.DATAAREAID = 'dat' AND
InventDim.INVENTDIMID = InventTrans.INVENTDIMID
WHERE InventTrans.DATAAREAID = 'dat' AND
InventTrans.ITEMID = '027743' AND
InventDim.INVENTLOCATIONID = 'КзРЦ Алмат' AND
InventDim.ECC_BUSINESSUNITID = 'Казахстан';
План запроса (с TOP):
Статистика запросов ввода-вывода и времени (с TOP):
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
(0 row(s) affected)
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'INVENTTRANS'. Scan count 15385, logical reads 82542, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'INVENTDIM'. Scan count 1, logical reads 62704, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row(s) affected)
SQL Server Execution Times:
CPU time = 265 ms, elapsed time = 257 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 0 ms.
Используемые индексы (с ТОПом):
1. INVENTTRANS.I_177TRANSIDIDX
4 KEYS:
- DATAAREAID
- INVENTTRANSID
- INVENTDIMID
- RECID
2. INVENTTRANS.I_177DIMIDIDX
3 KEYS:
- DATAAREAID
- INVENTDIMID
- ITEMID
3. INVENTDIM.I_698DIMIDIDX
2 KEYS:
- DATAAREAID
- INVENTDIMID
4. INVENTDIM.I_698ECC_BUSUNITLOCIDX
3 KEYS
- DATAAREAID
- ECC_BUSINESSUNITID
- INVENTLOCATIONID
Буду глубоко признателен за любую помощь по теме!
Ответы:
SQL Server строит разные планы выполнения для TOP 100, используя другой алгоритм сортировки. Иногда это быстрее, иногда медленнее.
Для более простых примеров, прочитайте, сколько может одна строка изменить план запроса? Часть 1 и Часть 2 .
Подробные технические подробности, а также пример того, где алгоритм TOP 100 на самом деле медленнее, читайте в статье Сортировка Пола Уайта, Цели строк и Проблема TOP 100 .
Суть: в вашем случае, если вы знаете, что строки не будут возвращены, ну ... не выполняйте запрос, а? Самый быстрый запрос - тот, который вы никогда не делаете. Однако, если вам нужно выполнить проверку существования, просто выполните IF EXISTS (придерживайтесь запроса здесь), и тогда SQL Server выполнит даже другой план выполнения.
источник
Глядя на эти два плана, у вас есть ключевой поиск по обоим с резко различающимися% расходов. Если навести указатель мыши на объекты, вы увидите количество выполнений.
Поиск по ключу - это возврат к кластерному индексу, поскольку индекс, используемый при поиске по индексу (вверху справа), не охватывает все столбцы (выберите *, поэтому необходимо использовать кластерный индекс).
Топ-100 может получить 100 строк, необходимых при меньшем чтении из индекса, и затем выполнить поиск 100 раз, а не для каждой строки в таблице. Также объясняется увеличение количества прочитанных страниц, когда НЕ выполняется «top».
источник