Temos uma tabela CustomerNote com 4 colunas ID, CustomerID, Note, Date
Existe um índice em CustomerID asc, Date desc
Quando a seguinte consulta é executada
select top 30
Date
from CustomerNote
where CustomerID in (1,5)
order by Date desc
O índice é usado, mas ainda está buscando TODAS as CustomerNotes para os customerIDs 1 e 5, para então classificar/topar, causando muito uso da CPU.
Isso ocorre devido aos vários valores na cláusula "in". Eu sei que a cláusula "in" nunca terá mais valores do que 10, então seria uma abordagem muito melhor se o sql server iterasse sobre os 10, buscasse pelo menos 30 por customerID e a mesclagem, classificações e tops. Existe uma dica de consulta ou opção para conseguir isso?
Provavelmente é melhor escrever a transformação que deseja manualmente, mas com o objetivo de encontrar algo que o otimizador possa fazer por você com alterações mínimas:
Sim, seria bom se o otimizador explorasse esse tipo de opção para você sem alterar a sintaxe.
Exemplo de tabela e dados
Isso carrega 2.047 valores de data aleatórios para dez clientes diferentes:
A execução do código da solução produz um plano de pós-execução em que 14 linhas são lidas de uma busca de índice ordenada para o cliente 1 e 17 linhas de uma busca semelhante para o cliente 5:
db<> demonstração de violino
O plano não lê todas as 2.047 linhas para cada cliente.
Observe também que esta solução não requer um operador de classificação.
A solução é bastante geral, embora existam algumas condições de classificação a serem atendidas para a Merge Concatenation .
Se você deseja projetar uma coluna diferente, essa coluna precisaria fazer parte da chave de índice (não como uma inclusão) para atender ao requisito de classificação; ou você pode buscar apenas uma chave para a tabela e procurar a(s) coluna(s) extra(s) como uma etapa separada depois de encontrar o pequeno número necessário de chaves.
Demonstrações adicionais com uma coluna extra:
Parece que pode ser melhor se você juntar um parâmetro com valor de tabela, tabela temporária ou
VALUES
cláusula. Isso significa que cada umCustomerID
será consultado individualmente de forma correlacionadaAPPLY
e depois classificado.Os
top
eorder by
são sempre aplicados por último. Você não pode esperar que o otimizador faça uma pré-filtragem de linhas com base naorder by
cláusula.Mas você pode reduzir o número de registros para classificação, usando algo como
Portanto, supondo que você tenha mais de 30 registros nos últimos sessenta dias, você obterá esses registros, os classificará e descartará os extras. O número real de dias, você teria que adivinhar, com base em seus dados.