Pregunta de rendimiento 'SELECCIONAR SUPERIOR'

18

Tengo una consulta que se ejecuta mucho más rápido con select top 100y mucho más lento sin top 100. El número de registros devueltos es 0. ¿Podría explicar la diferencia en los planes de consulta o compartir enlaces donde se explica esa diferencia?

La consulta sin toptexto:

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 = 'Казахстан';

El plan de consulta para lo anterior (sin top):

https://pastebin.com/cbtJpxFf

ingrese la descripción de la imagen aquí

Las estadísticas IO y TIME (sin 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.

Los índices utilizados (sin 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

La consulta con 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 = 'Казахстан';

El plan de consulta (con TOP):

https://pastebin.com/0dyu6QZd

ingrese la descripción de la imagen aquí


La consulta de estadísticas IO y TIME (con 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.

Los índices utilizados (con TOP):

 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

¡Apreciará profundamente cualquier ayuda sobre el tema!

George K
fuente
2
No creo que la velocidad de 'TOP' sin 'ORDER BY' importe. Los resultados correctos son más importantes que la velocidad.
Dan Guzman
3
Relacionado: tal vez un duplicado ¿Cómo (y por qué) TOP impacta un plan de ejecución?
Paul White reinstala a Monica

Respuestas:

15

SQL Server crea diferentes planes de ejecución para TOP 100, utilizando un algoritmo de ordenación diferente. A veces es más rápido, a veces es más lento.

Para ver ejemplos más simples, lea ¿Cuánto puede una fila cambiar un plan de consulta? Parte 1 y Parte 2 .

Para obtener detalles técnicos detallados, además de un ejemplo de dónde el algoritmo TOP 100 es realmente más lento, lea la Clasificación de Paul White, los Objetivos de fila y el Problema TOP 100 .

La conclusión: en su caso, si sabe que no se devolverán filas, bueno ... no ejecute la consulta, ¿eh? La consulta más rápida es la que nunca haces. Sin embargo, si necesita hacer una verificación de existencia, simplemente haga SI EXISTE (consulta aquí), y luego SQL Server hará un plan de ejecución incluso diferente.

Brent Ozar
fuente
Gracias, definitivamente lo leeré. También he notado que las estimaciones de filas son incorrectas en ambos escenarios. ¿Con qué podría estar conectado? Las estadísticas están bien: lo he actualizado con la opción fullscan en ambos índices agrupados.
George K
Además, ¿es adecuado en mi caso ya que no tengo ningún PEDIDO, por lo que creo que no habrá SORT en mi plan?
George K
Será muy interesante ver si el plan de ejecución es el mismo para TOP 100 y TOP 101. Si es posible, por favor comparta. Gracias.
Artashes Khachatryan
@ GeorgeK Puedo ver que está utilizando Dynamics AX. Tenga cuidado con la marca de seguimiento [ blogs.msdn.microsoft.com/axinthefield/… que puede generar muchos problemas de estimación. Si el indicador de seguimiento 4136 está desactivado, compruebe si la columna "Partición" es la primera en sus índices. La partición generalmente tiene muy pocos valores distintos.
Hans Vader
9

Mirando los dos planes, tiene una búsqueda clave en ambos con costos porcentualmente diferentes. Si pasa el mouse sobre los objetos, verá el número de ejecuciones.

La búsqueda de claves es una búsqueda de regreso al índice agrupado ya que el índice utilizado en la búsqueda de índice (arriba a la derecha) no cubre todas las columnas (seleccione *, por lo que debe usarse el índice agrupado).

Top 100 puede obtener las 100 filas necesarias en menos lecturas del índice y luego realizar la búsqueda 100 veces en lugar de cada fila de la tabla. También explica el aumento en el número de páginas leídas cuando NO se hace el 'top'.

Simon Hellings
fuente