Estou lutando com o ajuste de uma das consultas em nosso SQL Server 2016 SP2 de produção. Eu precisava anonimizar a consulta devido às políticas de segurança. A consulta é assim:
SELECT TOP 1000 Object1.Column1,Object1.Column2,Object1.Column3,Object1.Column4,Object1.Column5,Object1.Column6,Object1.Column7,Object1.Column8,Object1.Column9,Object1.Column10,Object1.Column11,Object1.Column12,Object1.Column13,Object1.Column14,Object1.Column15,Object1.Column16,Object1.Column17,Object1.Column18,Object1.Column19,Object1.Column20,Object1.Column21,Object1.Column22,Object1.Column23,Object1.Column24,Object1.Column25,Object1.Column26,Object1.Column27,Object1.Column28,Object1.Column29,Object1.Column30,Object1.Column31,Object1.Column32,Object1.Column33,Object1.Column34,Object1.Column35,Object1.Column36,Object1.Column37,Object1.Column38,Object1.Column39,Object1.Column40,Object1.Column41,Object1.Column42,Object1.Column43,Object1.Column44,Object1.Column45,Object1.Column46,Object1.Column47,Object1.Column48,Object1.Column49,Object1.Column50,Object1.Column51,Object1.Column52
FROM Schema1.Object2 Object1
LEFT OUTER JOIN Schema1.Object3 Object4 ON Object4.Column3 = Object1.Column3
WHERE ((Object1.Column43 IS NULL OR Object1.Column43='') AND (Object4.Column54 = 0 OR Object4.Column54 IS NULL) AND Object1.Column3 = N'SomeValue')
ORDER BY Object1.Column3 ASC,Object1.Column8 ASC,Object1.Column7 ASC,Object1.Column12 ASC,Object1.Column13 ASC,Object1.Column1 ASC
O plano de consulta real pode ser encontrado aqui
Como você pode ver, uma busca de índice é feita em Object2.Index1.Object1, mas as estimativas são terríveis. O SQL Server estimou que 194.907 linhas retornariam, mas apenas 710 linhas são retornadas.
Quando removo a ORDER BY
cláusula as estimativas são muito melhores, o SQL Server esperava que apenas 1181 linhas voltassem. O plano pode ser encontrado aqui .
O que eu não entendo é por que um ORDER BY
pode influenciar as estimativas de um índice de busca. Ambas as consultas são executadas com o mesmo valor para column3.
Alguém pode me explicar isso?
Esta é uma consulta de valores principais. O ORDER BY especifica quais 1.000 linhas a consulta retornará. Sem o ORDER BY o SQL Server é livre para retornar qualquer 1000. Assim, uma vez que o SQL Server tenha 1000 linhas de Schema1.Object2 que se qualifiquem na cláusula WHERE, ele pode parar. O LEFT JOIN não pode reduzir o número de linhas.
Especificamente, o plano no-ORDER BY tem um objetivo de linha quando lê Object2:
O plano ORDER BY não. Ele precisará classificar todas as linhas filtradas antes de descobrir quais 1000 retornar.