Eu gostaria de ajustar esta consulta - ela está lendo mais linhas do que eu gostaria. Adicionei um índice conforme sugerido pelo Database Tuning Advisor.
A consulta fica assim:
SET STATISTICS TIME, IO ON;
SELECT TOP 1000 project,
Max(timestamp) timestamp
FROM the_table
WHERE deviceid = 581
GROUP BY project
As estatísticas IO , Time são assim:
Table 'the_table'. Scan count 1, logical reads 2373, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
(1 row affected)
SQL Server Execution Times:
CPU time = 390 ms, elapsed time = 829 ms.
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 0 ms.
O plano de execução pode ser encontrado aqui .
O dta_index que esta consulta procura consiste em projectnumber
e timestamp
. A tabela tem aproximadamente 4.500.000 linhas, consumindo aproximadamente 350 MB e cada uma deviceid
tem aproximadamente a mesma quantidade de registros (ou seja, distribuição uniforme e cada dispositivo tem aproximadamente 700 mil registros).
Meu problema: embora eu esteja solicitando apenas as primeiras 1.000 linhas da tabela, não importa o índice que criei ou como tentei reescrever a consulta, sempre acabei lendo +/- 700K linhas (ou seja, todas as linhas para o dispositivo selecionado na WHERE
cláusula). Eu ficaria grato se você pudesse deixar suas dicas sobre como ajustar esta consulta.
Eu não acho que haja uma maneira de restringir essa consulta mais rápido do que tocar as linhas de aproximadamente 700K para particular deviceid
com o primeiro operador de exec. plano.
Aqui está um exemplo reproduzível mínimo, incluindo a definição da tabela e a inserção de duas linhas de amostra:
CREATE TABLE [dbo].[the_table]
(
[primary_key_col] [int] IDENTITY(1,1) NOT NULL,
[Project] [int] NULL,
[DeviceID] [int] NULL,
[TimeStamp] [datetime] NULL,
[Quantity] [int] NOT NULL,
PRIMARY KEY CLUSTERED
(
[primary_key_col] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];
SET IDENTITY_INSERT [dbo].[the_table] ON;
INSERT [dbo].[the_table] ([primary_key_col], [Project], [DeviceID], [TimeStamp], [Quantity]) VALUES (4825107, 1232, 587, CAST(N'2021-10-23T05:48:48.000' AS DateTime), 1);
INSERT [dbo].[the_table] ([primary_key_col], [Project], [DeviceID], [TimeStamp], [Quantity]) VALUES (4825108, 6458, 581, CAST(N'2021-10-23T05:49:17.000' AS DateTime), 1);
coluna_primária_chave | Projeto | ID de dispositivo | Carimbo de hora | Quantidade |
---|---|---|---|---|
4825107 | 1232 | 587 | 23-10-2021 05:48:48.000 | 1 |
4825108 | 6458 | 581 | 23-10-2021 05:49:17.000 | 1 |
Os índices não fazem parte da questão deliberadamente, não importa qual índice eu tente, sempre atingi 700 mil linhas para um deviceID específico.
Obrigado.
"Meu problema: mesmo que eu esteja lendo apenas as primeiras 1000 linhas da tabela" Você não está. Você está lendo os primeiros 1000 resultados (sem qualquer ordenação) da consulta agrupada -
top 1000
vem por último na ordem de processamento.Se você quiser obter 1.000 linhas "aleatórias" que correspondam ao
deviceid
predicado, poderá usar uma subconsulta:Desculpe, mas do meu ponto de vista, você deve repensar sua lógica de consulta, porque ela obtém todas as linhas correspondentes
deviceid
e pega as 1000 principais dessas linhas correspondentes, não as 1000 principais da tabela. Você pode ver isso também em seu plano de execução: do lado direito está uma tabela de buscadeviceid
e TOP é o último operador do lado esquerdo. É por isso que você obtém essa quantidade de linhas.