Eu tenho uma tabela particionada que é particionada com base em col1 int. Eu também tenho um índice de cobertura para a consulta que estou tentando solucionar.
https://www.brentozar.com/pastetheplan/?id=BkNrNdgHm
Acima está o plano
Deixado a seu critério, o SQL Server decide fazer uma verificação de índice clusterizado de toda a tabela, o que obviamente é lento. Se eu forçar o índice (como no plano acima), a consulta será executada rapidamente.
Que lógica mágica o SQL Server usa para decidir que o índice coberto não é útil? Não tenho certeza se top/orderby e rowgoal tem alguma coisa a ver com isso.
A estrutura da minha tabela é
Create table object2(col1 int, col3 datetime, col4 int, col5, col6 etc) clusterd on col1
nonclustered non aligned index is on col3,col4 (col1 is clustered so its included in nonclust)
SELECT top(?) Object1.Column1
FROM Object2 Object1 WITH (NOLOCK,index(Column2))
WHERE Object1.Column3 >= ?
AND Object1.Column4 IN (?)
ORDER BY Object1.Column1
Editar repositório adicionado
CREATE PARTITION FUNCTION [PFtest](int) AS RANGE RIGHT FOR VALUES (100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000)
GO
CREATE PARTITION SCHEME [PStest] AS PARTITION [PFtest] all TO ([PRIMARY]);
GO
create table test([ID] [int] IDENTITY(1,1) NOT NULL primary key clustered,[Created] [datetime] NULL,[Type] [int] NULL,text1 varchar(10),text2 varchar(20))
on pstest(id)
set nocount on
declare @a int =1
declare @type int
while 1=1
begin
if @a%30 =0
insert into test (Created, Type, text1, text2) select getdate(),4,'four','four'
else
insert into test (Created, Type, text1, text2) select getdate(),1,'one','one'
set @a=@a+1
end
create nonclustered index ncl1 on test(created, type)
select min(created),max(created) from test
--2018-08-02 22:46:40.187 2018-08-02 22:49:01.577
SELECT top(10) ID
FROM test
WHERE Created >= '2018-08-02 22:49:01'
AND Type IN (1, 4)
ORDER BY ID -- clustered index scan
SELECT top(10) ID
FROM test
WHERE Created >= '2018-08-02 22:49:01.577'
AND Type IN (1, 4)
ORDER BY ID-- index seek of ncl1
Sim, é mais provável que seja um problema de meta de linha.
O SQL Server avalia que a verificação do índice clusterizado (para evitar uma classificação) localizará as primeiras
?
correspondências mais rapidamente (no ponto em que a verificação será interrompida) do que pesquisar as correspondências no índice não clusterizado, classificá-las e retornar as principais?
correspondências.Em sua versão do SQL Server, você pode testar se definir uma meta de linha é a causa executando a consulta com
OPTION (QUERYTRACEON 4138)
para desabilitar metas de linha.Perguntas e respostas relacionadas:
Em termos gerais e mais básicos, se o custo de
Index scan
for menor queIndex Seek
então, o Optimizer pode decidirIndex Scan
.Neste caso, há muitos registros que são maiores
'2018-08-02 22:49:01'
e apenas 10 registros são desejados.portanto, se o Optimizer recuperasse o registro do Index, o custo seria maior.
Então ele
Index Scan
e este "Plano Bom o Suficiente Encontrado"Aqui há muito menos registro que é maior do que
'2018-08-02 22:49:01.577'
Portanto, desses 10 registros é o desejo que o Optimizer buscaIndex Seek
.Aqui você notará que o operador Index Seek retorna todas as linhas que são maiores que
'2018-08-02 22:49:01.577'
. O número real de linhas são todas as linhas que se qualificam maiores que'2018-08-02 22:49:01.577'
. Em seguida, o operador Classificar o fatia para 10.Portanto, pode não ser "Plano Bom o Suficiente Encontrado".