Se a resposta for 'não', tudo bem...
Estou olhando para ver se isso pode ser otimizado... é parte de um proc armazenado muito maior. CGCode
é varchar(50), Year
e Month
são smallint
, FEIN
échar(9)
select max(id)
from Table
where 1=1
and cgcode = 123
and datefromparts(cast(year as char(4)),cast(month as char(2)),'01') < getdate()
and totalcount > 0
group by cgcode, year, month, fein
Leituras lógicas do plano de execução real: 1.566.473
Dados brutos da tabela de origem mais de 32 milhões de registros
Linhas estimadas: 640K, 55K reais, antes do Group By entrar em ação
Avisos de conversão implícitos ativados Year/Month/CGCode
(entra como bigint
)
Tempo de execução de aproximadamente 7,5 segundos, fazendo uma busca de índice não clusterizado:
O conjunto de resultados finais é de 114 linhas (para isso CGCode
, testamos com... outros variam)
O desempenho é praticamente o mesmo no Prod em hardware significativamente melhor do que na caixa Dev. Isso só vai piorar com o tempo, pois está puxando tudo mais antigo que o mês atual, para preencher um gráfico de histórico em uma interface do usuário.
Que outras informações posso fornecer?
O índice que está sendo usado atualmente:
CREATE NONCLUSTERED INDEX [COIX_Table_TotalCount] ON [dbo].[Table]
(
[TotalCount] ASC
)
INCLUDE ( [ID],
[CGCode],
[Year],
[Month],
[FEIN])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF,
ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CGCode
limita os dados mais... 281 valores. year
é apenas 3-4 anos de dados, month
apenas 12 opções, é claro. TotalCount
é um bigint
, 17K valores distintos em 32 milhões de registros. Não faço ideia de qual é o propósito da TotalCount
coluna.
Em primeiro lugar, eu reescreveria essa condição. Como está, não pode usar nenhum índice de forma eficaz.:
Reescreva-o para que não haja funções ou cálculos aplicados às colunas:
A reescrita permitiria a utilização de um índice on
(cgcode, year, month)
- ou melhor ainda(cgcode, year, month, fein)
, considerando asGROUP BY
partes.Em seguida, se
totalcount
sempre fizer parte daWHERE
cláusula ou se atotalcount > 0
condição específica for sempre usada, você poderá obter ainda mais eficiência adicionando-a àINCLUDE
parte ou com um índice filtrado e mais direcionado:Vou remover o cgcode do Group By, pois sei o que é cgcode e não é range.
Então, se eu estiver correto, meu índice também mudará.
Use Variable no lugar de getdate()
Também tecnicamente porque
totalcount will be covering index
na opção AI não entendo, por essa lógica deve estar dentro do grupo de índices ouoption B
está correto.Encontrei :)
O clientid está sendo passado como INT... causando uma conversão implícita para varchar para o campo CGCode.
De 7-30 segundos a 100ms. Eu vou levar isso.