Melhorando a Performance de Consultas no Totvs Protheus – Parte 3

Fala pessoal,
Antes de lerem esse post, caso ainda não tenham lido os anteriores, sugiro que façam para seguirem a linha de raciocínio:
- https://www.fabriciolima.net/blog/2017/12/11/melhorando-a-performance-de-consultas-no-totvs-protheus-parte-1/
 - https://www.fabriciolima.net/blog/2017/12/18/melhorando-a-performance-de-consultas-no-totvs-protheus-parte-2/
 
Pegando mais uma quey no Traces de queries demoradas. Durante a semana, essa query apareceu várias vezes demorando mais de 3 segundos. Contudo, no fim de semana, ao rodar ela sem concorrência, ela está instantânea.
Nesse caso eu faço o que Fabricio? Ignoro?
Não. Vi que tem índices triviais nessa query que não existem, então vamos criar para reduzir a quantidade de leituras dela:
| 
					 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18  | 
						SELECT   C6_NUM ,          C6_QTDVEN ,          C6_NOTA ,          C6_CLI ,          C6_PRCVEN ,          C5_EMISSAO ,          C5_YSTATUS ,          C5_VEND1 FROM     SC6080 SC6 ,          SC5080 SC5 WHERE    C6_FILIAL = C5_FILIAL          AND C5_NUM = C6_NUM          AND C6_PRODUTO = 'BHASJHSU654556'          AND C6_FILIAL = '01'          AND SC6.D_E_L_E_T_ = ''          AND SC5.D_E_L_E_T_ = '' ORDER BY C5_EMISSAO ,          C6_NUM;  | 
					
Segue o plano dessa query:

O SQL Server está fazendo Seek+lookup nas duas tabelas envolvidas (SC5080 e SC6080).
Levando em conta a Parte 1 e Parte 2 da série Fabrício, devemos tentar criar um índice apenas em C6_PRODUTO para ver se já resolve a query?
Veja bem….
Vamos criar para verem o que vai acontecer.
| 
					 1  | 
						create nonclustered index SC6080W01 on SC6080(C6_PRODUTO)with(FILLFACTOR=90,DATA_COMPRESSION=PAGE)  | 
					
Ao criar o índice, o SQL Server não usou o índice e a query rodou com o mesmo plano de execução anterior.
Oxente Fabrício… venha cá… mas por que não usou?
obs.: Estou atendendo um cliente em Salvador hoje (08/01) e peguei o sotaque.
R: Porque essa query retorna mais de 2 mil linhas no resultado.
Gravem isso que é muito importante: Fazer um lookup em poucas linhas é tranquilo, agora fazer um lookup em muitas linhas é custoso e esse é o motivo do SQL não querer usar o nosso índice por essa coluna única.
Como essa tabela não é tão grande e esse índice em produto tem tudo para ser bom por ser uma coluna bem seletiva, vamos criar um covered index (índice com todas as colunas necessárias para executar essa query).
| 
					 1 2 3  | 
						create nonclustered index SC6080W01 on SC6080 (C6_PRODUTO,C6_NUM,C6_FILIAL,D_E_L_E_T_ ) include(C6_NOTA,C6_CLI,C6_QTDVEN,C6_PRCVEN) with(FILLFACTOR=90,DATA_COMPRESSION=PAGE)  | 
					
A quantidade de leituras na tabela SC6080 já reduziu para 15 reads e a query ficou com esse plano:

Olhando os índices da tabela SC5080, já existe um índice na coluna C5_NUM criado por mim para alguma outra query nesse cliente, contudo esse índice só possui 4 colunas:
| 
					 1  | 
						C5_NUM, C5_FILIAL, C5_TIPO, D_E_L_E_T_  | 
					
Como esse índice não tem todas as colunas que a query precisa, o SQL não está usando.
Vamos adicionar todas as colunas da tabela SC5 utilizada pela query para ver se agora o SQL vai usar meu índice:
| 
					 1 2 3  | 
						create nonclustered index SC5080W01 on SC5080 (C5_NUM, C5_FILIAL, C5_TIPO, D_E_L_E_T_,C5_EMISSAO) include(C5_YSTATUS,C5_VEND1) with(FILLFACTOR=90,DATA_COMPRESSION=PAGE)  | 
					
Agora sim o SQL passou a usar os meus 2 índices para essa query:

Segue a diferença de leituras com a criação dos índices:
| 
					 1 2 3 4 5 6 7  | 
						-- Antes dos índices Table 'SC5080'. Scan count 2319, logical reads 14538 Table 'SC6080'. Scan count 1, logical reads 7121 --Depois dos índices Table 'SC5080'. Scan count 2319, logical reads 7423 Table 'SC6080'. Scan count 1, logical reads 15  | 
					
Tabela SC5080 rediziu 7 mil reads e a tabela SC6080 reduziu mais 7 mil reads.
Não foi um ganho tão grande quanto nos 2 casos anteriores, mas como são índices bons (PRODUTO e NUM), certamente esses índices devem ser utilizados para outras queries.
Lembrem disso: Um índice por uma coluna boa, não vai ser utilizado só pela query que você está analisando, certamente será utilizado por outras queries do sistema.
É isso ai pessoal, melhoramos mais uma query no Protheus.
Até a próxima análise.
Atualizado no dia 07/10/2020:
Publiquei um curso com 11 horas de duração com toda minha experiência de anos no assunto e de dezenas de clientes Protheus atendidos:
Curso: Melhorando a Performance de Consultas no Totvs Protheus
Gravei uma aula grátis com 60 minutos de duração sobre o que você deve aprender para melhorar a performance no Protheus:
Gostou desse Post?
Curta, comente, compartilhe com os coleguinhas…
Assine meu canal no Youtube e curta minha Página no Facebook para receber Dicas de Leituras e Eventos sobre SQL Server.
Até a próxima.
Abraços,
Fabrício Lima
Microsoft Data Platform MVP
Consultor e Instrutor SQL Server
Trabalha com SQL Server desde 2006

Curti, espero mais postagens sobre banco de dados no Protheus! parabens!!!
Show. tem 7 iguais a esse. Aproveite.