Pergunta de desempenho 'SELECT TOP'

18

Eu tenho uma consulta que roda muito mais rápido com select top 100e muito mais lento sem top 100. O número de registros retornados é 0. Você poderia explicar a diferença nos planos de consulta ou compartilhar links onde essa diferença foi explicada?

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

O plano de consulta para o acima (sem top):

https://pastebin.com/cbtJpxFf

insira a descrição da imagem aqui

As estatísticas de IO e TIME (sem 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.

Os índices usados ​​(sem 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

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

O plano de consulta (com TOP):

https://pastebin.com/0dyu6QZd

insira a descrição da imagem aqui


As estatísticas de IO e TIME da consulta (com 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.

Os índices usados ​​(com 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 qualquer ajuda sobre o tema!

George K
fonte
2
Eu não acho que a velocidade do 'TOP' sem 'ORDER BY' seja importante. Resultados corretos são mais importantes que velocidade.
Dan Guzman
3
Relacionado: talvez uma duplicata Como (e por que) o TOP afeta um plano de execução?
Paul White diz GoFundMonica

Respostas:

15

O SQL Server cria diferentes planos de execução para o TOP 100, usando um algoritmo de classificação diferente. Às vezes é mais rápido, às vezes é mais lento.

Para exemplos mais simples, leia Quanto uma linha pode alterar um plano de consulta? Parte 1 e Parte 2 .

Para detalhes técnicos detalhados, além de um exemplo de onde o algoritmo TOP 100 é realmente mais lento, leia Classificação, metas de linha e problema do TOP 100 , de Paul White .

A linha inferior: no seu caso, se você souber que nenhuma linha será retornada, bem ... não execute a consulta, hein? A consulta mais rápida é aquela que você nunca faz. No entanto, se você precisar fazer uma verificação de existência, faça IF EXISTS (consulte a consulta aqui) e o SQL Server executará um plano de execução ainda diferente.

Brent Ozar
fonte
Obrigado, com certeza vou ler. Também notei que as estimativas de linhas estão incorretas nos dois cenários. Com o que ele pode estar conectado? As estatísticas, se bem - eu atualizei com a opção fullscan em ambos os índices em cluster.
George K
Além disso - é adequado no meu caso, pois não tenho nenhuma ORDEM, então acredito que não haverá SORT no meu plano?
George K
Será muito interessante ver se o plano de execução é o mesmo para os TOP 100 e TOP 101. Se for possível, compartilhe. Obrigado.
Artashes Khachatryan #
@ GeorgeK Posso ver que você está usando o Dynamics AX. Cuidado com o sinalizador de rastreamento [ blogs.msdn.microsoft.com/axinthefield/…, que pode levar a muitos problemas de estimativa. Se o sinalizador de rastreamento 4136 estiver desativado, verifique se a coluna "Partição" é a primeira em seus índices. Partição geralmente possui muito poucos valores distintos.
Hans Vader
9

Olhando para os dois planos, você tem uma pesquisa importante de ambos com custos% diferentes. Se você passar o mouse sobre os objetos, verá o número de execuções.

A pesquisa de chave é uma pesquisa de volta ao índice clusterizado, pois o índice usado na busca de índice (canto superior direito) não cobre todas as colunas (selecione * para que o índice clusterizado seja usado).

As 100 principais são capazes de obter as 100 linhas necessárias em menos leituras do índice e, em seguida, executar a pesquisa 100 vezes em vez de todas as linhas da tabela. Também explica o aumento no número de páginas lidas quando NÃO está no 'topo'.

Simon Hellings
fonte