Eu registrei as consultas mais lentas no meu banco de dados e uma me surpreendeu, aparecendo muitas vezes na lista e demorando muitos segundos para ser executada.
UPDATE books SET last_read='2018-12-31 11:23:45' WHERE book_id='15'
book_id é int identity PK (clustered), last_read é um datetime. A consulta é escrita com o 15 entre aspas simples, exigindo assim uma conversão, mas não posso imaginar que isso seja um grande problema, porque a conversão seria feita apenas uma vez por consulta. Existem 6 índices na tabela, mas a coluna last_read não está envolvida ou incluída em nenhum deles. O PK está no book_id e não tem nada de especial. A tabela é muito central no banco de dados, contém 50 colunas e 400.000 linhas.
O plano de execução estimado me diz:
UPDATE: 0%
Clustered Index Update (on the PK constraint): 100%
A tabela tem um gatilho FOR DELETE, que considero irrelevante aqui, e um gatilho AFTER UPDATE, que diz:
CREATE TRIGGER books_last_update
ON books
AFTER UPDATE
AS
UPDATE books
SET last_update = GETDATE()
WHERE book_id IN (SELECT book_id FROM Inserted)
GO
Isso me mostra que a consulta inicial realmente executa duas consultas, uma após a outra. No entanto, ambas as colunas atualizadas não têm índice definido. Eu gostaria de fazer a consulta inicial executar mais rápido.
Você vê alguma otimização possível?
Receio que, como o gatilho está em UPDATE e, na verdade, atualiza a coluna, ele pode ser acionado várias vezes. É possível? Se sim, como faço para prevenir?
Então seu código deve dizer:
E não:
Isso não deve afetar o desempenho neste caso, mas é uma prática recomendada delimitar (ou não) corretamente. Strings e datas não Unicode com aspas simples, strings Unicode prefixadas com N, binários e numéricos sem aspas.
Não, o SQL Server é inteligente o suficiente para não se jogar de um penhasco. Ele reconhece que a atualização dentro do gatilho não deve chamar o gatilho recursivamente em um loop infinito. Você pode provar isso executando um rastreamento do lado do servidor ou uma sessão de eventos estendidos e verá que a atualização dentro do gatilho é executada apenas uma vez.
Você pode adicionar código para evitar que uma atualização dessa coluna acione uma segunda atualização (por exemplo, se alguém atualizou manualmente a
last_update
coluna, mas isso não parece relevante aqui).Geralmente, se você achar que os gatilhos estão diminuindo a velocidade do seu código (não vi nenhuma prova disso neste caso), procure se livrar dos gatilhos. Não tenho certeza de qual código de aplicativo está atualizando essa tabela diretamente, mas se você puder usar um procedimento armazenado para processar todas as atualizações da tabela, poderá adicionar a atualização a essa coluna, em vez de depender do gatilho. Mas suspeito que se você estiver esperando 5 segundos para que essa atualização aconteça, o gatilho NÃO é o problema.
Se o valor não mudar isso elimina um bloqueio e um gatilho