Eu tenho uma instância do SQL Server 2008 com aproximadamente 150 colunas. Eu preenchi anteriormente esta tabela com aproximadamente 12 milhões de entradas, mas desde então a limpou em preparação para um novo conjunto de dados.
No entanto, os comandos que uma vez correu imediatamente em uma mesa vazia, como count(*)
e select top 1000
em SQL Management Studio
tomar agora eras para ser executado.
SELECT COUNT(*) FROM TABLE_NAME
demorou 11 minutos para retornar 0 e SELECT TOP 1000
levou quase 10 minutos para retornar uma mesa vazia.
Também notei que o espaço livre no disco rígido desapareceu literalmente (de cerca de 100G a 20G). A única coisa que aconteceu foi uma única consulta que executei:
DELETE FROM TABLE_NAME
O que anda acontecendo no mundo?!?
TRUNCATE TABLE
vez deDELETE FROM
.Respostas:
Você já foi informado sobre por
TRUNCATE
que seria muito mais rápido / melhor / mais sexy do queDELETE
, mas ainda há uma pergunta a ser resolvida:Por que é
SELECT
mais lento após aDELETE
conclusão ?Isso ocorre porque
DELETE
apenas as linhas são fantasmas . A tabela é tão grande quanto quando tinha 12M linhas, mesmo que não tenha nenhuma. Para contar as linhas (0), leva o tempo necessário para contar 12M linhas. Com o tempo, o processo de limpeza de fantasmas coletará esses registros fantasma e desalocará as páginas que continham apenas fantasmas, e seus SELECTs irão acelerar. Mas agora, se você fizer o check-Skipped Ghosted Records/sec
in, o perfmon provavelmente disparará duranteSELECT COUNT(*)
. Você também pode acelerar as coisas pela reconstrução da tabela:ALTER TABLE ... REBUILD
.TRUNCATE
também teria resolvido esse problema, já que não deixa fantasmas para trás.Consulte também Dentro do mecanismo de armazenamento: limpeza do Ghost em profundidade .
fonte
DELETE
As instruções excluem linhas de uma tabela uma de cada vez, registrando cada linha natransaction log
, bem como mantendo aslog sequence number (LSN)
informações. Como você mencionou que sua tabela possui dados enormes (12 milhões de registros), após a exclusão do disco rígido sem espaço, verifique o tamanho do arquivo de log do banco de dados. Provavelmente teria crescido.uma maneira melhor teria sido:
fonte
(Originalmente, isso foi um comentário à resposta de @ DaveE, mas eu coloquei em sua própria resposta porque demorou muito)
TRUNCATE
é uma operação registrada. Tem que ser de outra forma, não é compatível com ACID. No entanto, diferenças entreTRUNCATE
eDELETE
:TRUNCATE
registra apenas páginas / extensões * liberadas, enquantoDELETE
registra linhas individuais.TRUNCATE
geralmente usa menos bloqueios, já que são necessários bloqueios de tabela e bloqueios de página, ao contrário dosDELETE
bloqueios de linha **.IDENTITY
sequências:TRUNCATE
redefine a sequência de identidade em uma tabela, se presente.(* Uma extensão = 8 páginas.
TRUNCATE
Registrará / removerá extensões se todas pertencerem a essa tabela; caso contrário, registrará / removerá páginas de extensões misturadas.** Um efeito colateral disso é que
DELETE FROM TABLE
pode deixar páginas vazias alocadas para a tabela, dependendo se a operação pode ou não obter um bloqueio exclusivo da tabela.)Então (voltando à pergunta original),
TRUNCATE TABLE
é conclusivamente melhor do queDELETE FROM TABLE
se você estiver esvaziando a tabela, mas quiser manter a estrutura (NB:TRUNCATE
não pode ser usado em uma tabela referenciada por uma chave estrangeira de outra tabela).Conforme observado no comentário de @ Tullo, verifique também o modelo de recuperação do seu banco de dados - se estiver cheio, você precisará começar a fazer backups de log ou alterar seu modelo de recuperação para simples. Depois de fazer uma dessas opções, você provavelmente reduzirá seu arquivo de log como uma operação única (NB: somente arquivo de log ) para recuperar todo esse espaço livre.
Finalmente, outra coisa a ter em atenção - as estatísticas da tabela. execute
UPDATE STATISTICS <TABLENAME>' after
TRUNCATE/
DELETE` para que o otimizador de consultas não seja acionado por estatísticas antigas.fonte
(NOTA: eu não sou um DBA) DELETE é uma operação registrada e não libera o espaço usado. Você provavelmente tem um grande log de transações ocupando varreduras de espaço e tabela em execução no espaço de tabela 'vazio'. Eu acho que você precisa limpar o log de transações e reduzir seu banco de dados. Este artigo StackOverflow deve começar.
E use TRUNCATE TABLE quando desejar fazer isso no futuro.
Edição: Minha declaração sobre TRUNCATE não está sendo registrado estava com erro. removido.
fonte