Tenho uma tabela PaymentItems
com 8 milhões de linhas. 100.000 linhas têm a chave estrangeira PaymentItemGroupId = '662162c6-209c-4594-b081-55b89ce81fda'
.
Criei um índice não clusterizado na coluna PaymentItems.Date
(ASC) para poder classificar/encontrar entradas mais rapidamente para datas.
Ao executar a seguinte consulta, levará cerca de 3 minutos:
SELECT TOP 10 [p].[Id], [p].[Receivers]
FROM [PaymentItems] AS [p]
WHERE [p].[PaymentItemGroupId] = '662162c6-209c-4594-b081-55b89ce81fda'
ORDER BY [p].[Date]
O interessante é que, sem o TOP 10, levará 18 segundos e retornará todas as 100.000 linhas. Quando eu ordeno decrescente em vez de crescente ( ORDER BY [p].[Date] DESC
), levará cerca de 1 segundo. Quando eu removo o índice, também é mais rápido ao classificar de forma crescente.
Analisei o plano de consulta para a consulta lenta e parece que o MS SQL Server não filtra as linhas pela chave estrangeira primeiro, mas classifica todas as 8 milhões de linhas primeiro (varredura de índice não agrupada no Date
índice).
Na consulta rápida, ele filtrará primeiro as condições where (pesquisa de chaves agrupada).
Há algo que eu possa fazer além de remover o índice para Date
evitar que o SQL Server crie um plano de consulta ruim como esse?
Aqui está o plano de consulta real: https://www.brentozar.com/pastetheplan/?id=xBBArQl9kh
Aqui está o script de criação da tabela:
CREATE TABLE [dbo].[PaymentItems](
[Id] [uniqueidentifier] NOT NULL,
[PaymentItemGroupId] [uniqueidentifier] NOT NULL,
[Date] [datetime2](7) NOT NULL,
CONSTRAINT [PK_PaymentItems] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_PaymentItems_Date] ON [dbo].[PaymentItems]
(
[Date] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_PaymentItems_PaymentItemGroupId] ON [dbo].[PaymentItems]
(
[PaymentItemGroupId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
Para que essa consulta seja executada rapidamente, você precisaria do seguinte índice, que parece que você não tem. Isso impediria a consulta de chaves inteiramente, cobrindo completamente a consulta.
Chaves estrangeiras não são indexadas por padrão (embora devessem ser) e, mesmo se fossem, você não teria a
Date
coluna de chave.