Eu tenho uma tabela de dados grande. Existem 10 milhões de registros nesta tabela.
Qual é a melhor maneira para esta consulta
Delete LargeTable where readTime < dateadd(MONTH,-7,GETDATE())
sql-server
sql-server-2008
sql-optimization
user3107343
fonte
fonte
Respostas:
Se você estiver excluindo todas as linhas dessa tabela, a opção mais simples é truncar tabela, algo como
A tabela truncada simplesmente esvaziará a tabela, você não pode usar a cláusula WHERE para limitar as linhas que estão sendo excluídas e nenhum acionador será acionado.
Por outro lado, se você estiver excluindo mais de 80 a 90% dos dados, digamos que você tenha um total de 11 milhões de linhas e deseje excluir 10 milhões de outra maneira seria Inserir esses 1 milhão de linhas (registros que você deseja manter ) para outra tabela de preparação. Trunque esta tabela grande e insira novamente essas 1 milhão de linhas.
Ou, se permissões / visualizações ou outros objetos que possuem essa tabela grande como sua tabela subjacente não forem afetados ao soltar essa tabela, você poderá obter essa quantidade relativamente pequena de linhas em outra tabela, solte esta tabela e crie outra tabela com o mesmo esquema e importe-as linhas de volta para essa tabela ex-Large.
Uma última opção em que consigo pensar é alterar as configurações de seu banco de dados.
Recovery Mode to SIMPLE
e excluir linhas em lotes menores usando um loop while, algo como isto.e não se esqueça de alterar o modo de recuperação para completo e acho que você precisa fazer um backup para torná-lo totalmente afetivo (os modos de alteração ou recuperação).
fonte
optimal solution for unknown case
esse é o sonho, não é? Infelizmente você não pode curar todas as doenças com qualquer comprimido; Sugeri algumas soluções possíveis para diferentes cenários. Infelizmente não há bala de lasca aqui.A resposta @ m-ali está correta, mas lembre-se de que os logs podem crescer muito se você não confirmar a transação após cada bloco e executar um ponto de verificação. É assim que eu faria e considero este artigo http://sqlperformance.com/2013/03/io-subsystem/chunk-deletes como referência, com testes de desempenho e gráficos:
fonte
COMMIT TRANSACTION
eCHECKPOINT
os logs ainda estão crescendo. Obrigado por deixar isso claro.@Deleted_Rows
com 10000 ou pode acabar com um loop infinito devido à exclusão indefinida de pequenos conjuntos de dados. PortantoWHILE (@Deleted_Rows = 10000)
, assim que não houver uma "página" completa de dados para excluí-los, será interrompido. Na sua implementação,WHILE (@Deleted_Rows > 0)
o loop while será executado novamente, mesmo que tenha excluído apenas uma linha, e a próxima execução também poderá encontrar uma ou duas linhas para excluir - resultando em um loop infinito.WHILE
próprio loop:dateadd(MONTH,-7,GETDATE())
.WHILE
loop.Você também pode usar o GO + quantas vezes deseja executar a mesma consulta.
fonte
GO xx
deve funcionar? Eu recebo o erro "Não foi possível encontrar o procedimento armazenado ''" . Sem oGO
comando, ele funciona bem.@Francisco Goldenstein, apenas uma pequena correção. O COMMIT deve ser usado após você definir a variável, caso contrário, o WHILE será executado apenas uma vez:
fonte
Essa variação de M.Ali está funcionando bem para mim. Exclui alguns, limpa o log e repete. Estou vendo o log crescer, cair e começar de novo.
fonte
# of rows
para excluir de cada vez, e também aWHERE
cláusula. Funciona como um encanto!Se você deseja (e é capaz) implementar o particionamento, essa é uma técnica eficaz para remover grandes quantidades de dados com pouco tempo de execução. Não é rentável para um exercício único, no entanto.
fonte
Consegui excluir 19 milhões de linhas da minha tabela de 21 milhões de linhas em questão de minutos . Aqui está a minha abordagem.
Se você tiver uma chave primária de incremento automático nesta tabela, poderá usá-la.
Obtenha o valor mínimo da chave primária da tabela grande em que readTime <dateadd (MONTH, -7, GETDATE ()). (Adicione o índice no readTime, se ainda não estiver presente, esse índice será excluído de qualquer maneira junto com a tabela na etapa 3.). Permite armazená-lo em uma variável 'min_primary'
Insira todas as linhas com chave primária> min_primary em uma tabela intermediária (tabela de memória se o número de linhas não for grande).
Largue a mesa grande.
Recrie a tabela. Copie todas as linhas da tabela intermediária para a tabela principal.
Solte a mesa de preparação.
fonte
Você pode excluir pequenos lotes usando um loop while, algo como isto:
fonte
Outro uso:
Opcional;
Se o log de transações estiver ativado, desative os logs de transações.
fonte
Sintaxe mais curta
fonte
Se você estiver usando o SQL Server 2016 ou superior e se sua tabela estiver tendo partições criadas com base na coluna que você está tentando excluir (por exemplo, coluna Timestamp), poderá usar este novo comando para excluir dados por partições.
TABELA TRUNCATE WITH (PARTITIONS ({|} [, ... n])))
Isso excluirá os dados apenas na (s) partição (ões) selecionada (s) e deve ser a maneira mais eficiente de excluir dados de parte da tabela, uma vez que não criará logs de transações e será feito tão rápido quanto o truncado normal, mas sem que todos os dados sejam excluídos Da mesa.
A desvantagem é que, se sua tabela não estiver configurada com partição, você precisará ir à escola antiga e excluir os dados com abordagem regular e, em seguida, recriar a tabela com partições para que você possa fazer isso no futuro, e foi o que eu fiz. Eu adicionei a criação e exclusão da partição no próprio procedimento de inserção. Eu tinha uma tabela com 500 milhões de linhas, então essa era a única opção para reduzir o tempo de exclusão.
Para obter mais detalhes, consulte os links abaixo: https://docs.microsoft.com/en-us/sql/t-sql/statements/truncate-table-transact-sql?view=sql-server-2017
SQL Server 2016 Truncar tabela com partições
Abaixo está o que eu fiz primeiro para excluir os dados antes de poder recriar a tabela com partições com os dados necessários. Essa consulta será executada por dias durante a janela de tempo especificada até que os dados sejam excluídos.
fonte
Se eu digo sem loop, posso usar a
GOTO
instrução para excluir grande quantidade de registros usando o sql server. exa.dessa maneira, você pode excluir uma grande quantidade de dados com um tamanho menor de exclusão.
deixe-me saber se requer mais informações.
fonte