Eu tenho um banco de dados relativamente pequeno, talvez algumas centenas de milhares de linhas, e temos um procedimento armazenado que se destina a limpar um 'Dealer' (a raiz agregada do aplicativo) e todos os dados relacionados. O banco de dados reside em uma instância v12 do Azure SQL e, quando atinge uma tabela específica, consome 100% da DTU/CPU da instância e leva muito tempo para ser concluído.
Acredito que o problema é que a tabela tem uma tonelada de chaves estrangeiras, provavelmente cerca de 30. Observando o plano de execução, você pode ver que está fazendo uma tonelada Nested Loop
de varreduras de índice para encontrar linhas dependentes. Todas essas linhas já foram excluídas antes da tentativa de excluir as linhas dessa tabela específica, portanto, esses loops são realmente inúteis.
Minha pergunta é, seria mais eficiente desabilitar as restrições de chave estrangeira nessas tabelas dependentes, fazer a exclusão e reativar as restrições? Haveria algum efeito negativo em fazer isso, além do fato de ser tecnicamente possível que alguns dados ruins sejam inseridos enquanto as restrições estão desabilitadas. Ou existe uma maneira ainda melhor de realizar o que eu quero realizar?
ATUALIZAÇÕES Este é um banco de dados SQL do Azure v12, não é o SQL Server 2012 completo em uma VM. Não estou agrupando nenhuma exclusão e a instrução incorreta faz parte de um SPROC maior. Identifiquei essa exclusão de tabela em particular separando o sproc e executando pedaços dele separadamente. Quando chegou a esta mesa, levou literalmente 15 minutos para ser concluído. Isso afetará a ordem de centenas de linhas, variando dependendo do estado do 'Dealer' específico que estamos limpando.
Não podemos fazer exclusões temporárias neste caso porque geralmente estamos limpando esse revendedor para que ele possa ser substituído (exclusões temporárias causariam duplicação e exigiriam muito código para contornar). Eu investiguei outros tipos de bloqueio e estados de espera e não encontrei mais nada que parecesse estar afetando negativamente isso. Como mencionei, esse banco de dados é relativamente pequeno e é usado principalmente para operações CRUD muito simples.
Aqui está o plano de execução, é enorme.
A versão XML do plano de execução pode ser encontrada aqui: https://gist.github.com/CodingGorilla/6cf7a87df9257d5f93e0d545af9839c2