O que é melhor para grandes alterações em uma tabela: EXCLUIR e INSERIR sempre ou ATUALIZAR existente?


27

Estou fazendo um projeto no qual preciso alterar cerca de 36 mil registros em uma tabela diariamente. Eu estou querendo saber o que terá melhor desempenho:

  1. excluir linhas e inserir novas ou
  2. atualizar linhas já existentes

Para mim, é mais fácil excluir todas as linhas e inserir novas, mas se isso fragmentar a tabela e os índices e afetar o desempenho, eu preferiria fazer atualizações sempre que possível e excluir / inserir apenas quando necessário.

Será um serviço noturno e não pretendo melhorar a velocidade do processo em si. Estou mais preocupado com o desempenho de consultas nessa tabela em geral, onde já tenho 89 milhões de registros e como esse processo noturno o afetará.

Devo excluir / inserir registros ou atualizar os existentes (quando possível) para esse processo noturno?


Acredito que você deva fornecer mais detalhes sobre sua tabela, pois acho que isso dependeria da existência potencial de índices nos campos.
SRKX

Respostas:


9

Realmente depende de quanto dos dados estão mudando. Digamos que esta tabela tenha 20 colunas. E você também tem 5 índices - cada um em um diff. coluna.

Agora, se os valores em todas as 20 colunas estiverem mudando OU mesmo que os dados em 5 colunas estejam mudando e essas 5 colunas estejam todas indexadas, é melhor você "excluir e inserir". Mas se apenas duas colunas estiverem sendo alteradas e digamos que elas não fazem parte de nenhum índice não agrupado em cluster, é melhor "Atualizar" os registros porque, nesse caso, apenas o índice agrupado será atualizado (e os índices não precisarão ser atualizados). ser atualizado).


Em pesquisas adicionais, descobri que o comentário acima é meio redundante, pois o SQL Server possui internamente 2 mecanismos separados para executar uma atualização. - Uma "atualização no local" (ou seja, alterando o valor de uma coluna para um novo na linha original) ou como uma "ATUALIZAÇÃO não no local" (DELETE seguido por um INSERT).

As atualizações no local são a regra e são executadas, se possível. Aqui, as linhas permanecem exatamente no mesmo local, na mesma página e na mesma extensão. Somente os bytes afetados são trocados. O tlog possui apenas um registro (desde que não haja gatilhos de atualização). As atualizações acontecem se um heap estiver sendo atualizado (e houver espaço suficiente na página). As atualizações também acontecem se a chave de cluster mudar, mas a linha não precisar ser movida.

Por exemplo: se você possui um índice agrupado de sobrenome e tem os nomes: Capaz, Baker, Charlie Agora você deseja atualizar o Baker para Becker. Nenhuma linha precisa ser movida. Portanto, isso pode acontecer. Considerando que, se você precisar atualizar o Able para Kumar, as linhas deverão ser alteradas (mesmo que estejam na mesma página). Nesse caso, o SQL Server executará um DELETE seguido de um INSERT.

Considerando o exposto, sugiro que você faça uma atualização normal e deixe o SQL Server descobrir a melhor maneira de fazê-lo internamente.

Para obter mais detalhes sobre os internos "UPDATE" ou sobre os internos relacionados ao SQL Server, consulte o livro de Kalen Delaney, Paul Randal e outros - SQL Server 2008 Internals .


8

Você investigou o comando MERGE no SQL 2008? Aqui está um exemplo básico:

  merge YourBigTable ybt
  using (select distinct (RecordID) from YourOtherTable) yot
     on yot.Recordid = YBT.RecordID
  when NOT matched by target
  then  insert (RecordID)
        values (yot.DeviceID) ;

Este é basicamente um comando "UPSERT". Atualize, se existir, insira-o, se não existir. Comando MUITO rápido, muito legal.


11
Não é mais rápido que um UPDATE, a mesma mecânica sob o capô.
Mark Storey-Smith

É mais rápido que atualizar e depois inserir os que ainda não existiam.
datagod

2
Se você sabe que é o caso, prová-lo :)
Mark Storey-Smith

4

Mas, eu mesmo verifiquei a opção Excluir e Inserir vs Atualização em uma tabela com registros de 30 milhões (3crores). Esta tabela possui uma chave composta exclusiva em cluster e 3 chaves não clusterizadas. Para Excluir e Inserir, foram necessários 9 min. Para a atualização, foram necessários 55 min. Há apenas uma coluna que foi atualizada em cada linha.

Então, peço a vocês que não adivinhem. As equações serão alteradas ao lidar com tabelas grandes com muitas colunas e com muitos dados.


Também encontrei esse caso, mas descobri que às vezes é possível otimizar uma grande mesclagem adicionando indicações (temp ou perm) à origem ou destino, dicas ou sub-definindo o destino (não aplicável à mesclagem completa).
crokusek 14/02

3

A atualização não é tão rápida. O truque é conseguir uma inserção rápida, é desativar os índices enquanto os dados estão sendo inseridos.

Considere usar isto:

-- disable indexes
ALTER INDEX [index_name] ON dbo.import_table DISABLE
-- ... disable more indexes

-- don't use delete if you don't care about minimal logging. truncate is faster
TRUNCATE TABLE dbo.import_table

-- just insert the new rows
INSERT dbo.import_table
SELECT
    *
FROM
    dbo.source_table

-- rebuild indexes
ALTER INDEX [index_name] ON dbo.import_table REBUILD
-- ... rebuild more indexes

Ainda mais rápido é também desativar a atualização automática de estatísticas nas opções de banco de dados. Se a tabela for alterada significativamente, você deve executar:

UPDATE STATISTICS dbo.import_table

ou

EXEC sp_updatestats

como um trabalho regularmente (diariamente, semanalmente, dependendo do tamanho do banco de dados) para manter as estatísticas atualizadas. Uma coisa a observar é atualizar as estatísticas quando a tabela estiver vazia. Isso estragará as estatísticas se você não executá-lo depois que a tabela for preenchida novamente.


4
Não concordo que esse seja sempre o caso. Além disso, a tabela na pergunta do @ adopilotilot não pode ser limpa pelo TRUNCATE, pois contém 89 milhões de registros e ele deseja atualizar apenas 36k.
Mark Storey-Smith

precisa aprender a ler o post com mais cuidado! vou atualizar o post ... na verdade, preciso mudar bastante.
Perguntado
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.