Atualmente estou projetando uma tabela de transações. Percebi que será necessário calcular os totais em execução para cada linha e isso pode ser lento no desempenho. Então criei uma tabela com 1 milhão de linhas para fins de teste.
CREATE TABLE [dbo].[Table_1](
[seq] [int] IDENTITY(1,1) NOT NULL,
[value] [bigint] NOT NULL,
CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED
(
[seq] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
E tentei obter 10 linhas recentes e seus totais em execução, mas demorou cerca de 10 segundos.
--1st attempt
SELECT TOP 10 seq
,value
,sum(value) OVER (ORDER BY seq) total
FROM Table_1
ORDER BY seq DESC
--(10 rows affected)
--Table 'Worktable'. Scan count 1000001, logical reads 8461526, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Table 'Table_1'. Scan count 1, logical reads 2608, physical reads 516, read-ahead reads 2617, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Table 'Worktable'. Scan count 0, logical reads 0, 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 = 8483 ms, elapsed time = 9786 ms.
Suspeitei TOP
pelo motivo do desempenho lento do plano, então alterei a consulta assim e demorou cerca de 1 a 2 segundos. Mas acho que isso ainda é lento para a produção e me pergunto se isso pode ser melhorado ainda mais.
--2nd attempt
SELECT *
,(
SELECT SUM(value)
FROM Table_1
WHERE seq <= t.seq
) total
FROM (
SELECT TOP 10 seq
,value
FROM Table_1
ORDER BY seq DESC
) t
ORDER BY seq DESC
--(10 rows affected)
--Table 'Table_1'. Scan count 11, logical reads 26083, physical reads 1, read-ahead reads 443, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--
--(1 row affected)
--
-- SQL Server Execution Times:
-- CPU time = 1422 ms, elapsed time = 1621 ms.
Minhas perguntas são:
- Por que a consulta da 1ª tentativa é mais lenta que a 2ª?
- Como posso melhorar ainda mais o desempenho? Eu também posso mudar esquemas.
Apenas para esclarecer, ambas as consultas retornam o mesmo resultado abaixo.