Tenho uma consulta T-SQL semelhante a esta (um pouco mais complexa, simplificando aqui):
SELECT *
FROM ParticipantTable p
WHERE p.OrganizationId = @p__linq__0
AND p.ParticipantId IN (
@p__linq__1,
@p__linq__2,
@p__linq__3,
@p__linq__4,
@p__linq__5,
@p__linq__6,
@p__linq__7,
@p__linq__8,
@p__linq__9,
@p__linq__10
)
Isso resulta em um plano de consulta semelhante a este aqui (recortado na parte relevante):
Fiquei surpreso com o Clustered Index Seek realizando uma comparação maior que/menor que em vez de uma pesquisa "normal" por valor de chave de entrada:
Seek Keys[1]: Prefix: [snip].OrganizationId = Scalar Operator([@p__linq__0]); Start: [snip].ParticipantId > Scalar Operator([Expr1031]); End: [snip].ParticipantId < Scalar Operator([Expr1032])
Por que isso? Buscar um intervalo em não é uniqueidentifier
realmente ineficiente, resultando facilmente na seleção de um intervalo muito amplo de valores? Não seria muito mais eficiente fazer um loop nos valores de entrada e buscar um por um? Ou, com apenas dez valores, puxar os valores diretamente para o operador seek?
Imagino que isso possa ser apenas uma otimização porque a organização em questão tem um número baixo de participantes, mas não seria mais sensato extrair os valores para o operador de busca?
Além disso, apenas por interesse acadêmico, há uma maneira de forçar o SQL Server a buscar nos valores em vez do intervalo? WITH (FORCESEEK([snip](OrganizationId, ParticipantId))
não funciona, ele ainda buscará com maior que/menor que. Eu também adicionei OPTIMIZE FOR UNKNOWN
, mas realmente não esperava que fizesse nada aqui (e não fez).