none
Deletar registros sem prejudicar performace do banco. RRS feed

  • Pergunta

  • Bom dia,

    Preciso deletar uma grande quantidade de registros de algumas tabelas do meu banco.

    O problema é que se der o delete ou fazer um range de top 10000, o site, o qual utiliza o banco, fica extremamente lento.

    Alguém pode me ajudar com uma query onde eu possa deletar esses registros de forma rápida e sem sentar o site?

    Desde já obrigada!!!

    quarta-feira, 6 de novembro de 2013 13:16

Respostas

  • Helena, uma sugestão seria voce ao inves de deletar os 200MM de registros voce inserir em outra tabela os pouco menos de 30MM que voce não vai deletar, tendo todos estes registros em outra tabela crie o indice nela e voce pode dropar a tabela original e depois alterar o nome da tabela que voce colocou os 30MM para o nome da tabela original, isto afetaria o seu sistema poucos segundos durante o processo de deletar a tabela e renomear a nova.

    Outra sugestão seria voce verificar criar um job recursivo que rodaria a cada X minutos e deletar uma quantidade de registros determinada cada vez que ele roda, faça um teste por exemplo de quantos registros ele deletaria em 30 segundos, a partir deste numero voce pode colocar o job para deletar somente esta quantidade de registros a cada 5 minutos por exemplo.


    Alexandre Matayosi Conde Mauricio.

    quarta-feira, 6 de novembro de 2013 14:12
  • Amigo,

    Tenta utilizando o rowcount. Eu tilizo para apagar grandes quantidades de  linhas, sem encher completamente o espaço livre em disco. Suspeito que a nível de performace deva ser é melhor, já que pula a etapa de ordenar.

    set rowcount 10000

    while exists (select 1 from [tabela]where [filtro])
    begin

    delete from [tabela] where [filtro]
    checkpoint

    end

    Abraço;

    quarta-feira, 6 de novembro de 2013 13:35
  • Helena, bom dia !

    A tabela onde voce vai fazer o delete tem quantos registros ? destes quantos voce vai deletar ? no filtro que voce vai utilizar no delete existe indice nestes campos ? se sim veja como esta a fragmentação dos mesmos, muitas vezes um rebuild nos indices ajuda bastante.

    Uma outra opção seria voce deixar o delete agendado para rodar no horario de menor movimento do site, normalmente durante a madrugada dependendo do site.


    Alexandre Matayosi Conde Mauricio.

    quarta-feira, 6 de novembro de 2013 13:28
  • Senhores,

    Achei uma solução para minha pergunta.

    Fiz uma query onde crio uma tabela temporária e a populo com 10000 registros, sendo esses apenas minha PK.

    Em seguida crio um laço onde verifico se existe os registros de acordo com a condição necessária. Após isso deleto da minha tabela principal os registros que estão na tabela temporária.

    Com essa query consegui deletar milhões de registros em poucos minutos, sem prejudicar a performance do site.

    Acho que ficou meio confuso, por isso, segue a query utilizada:

    set nocount on
    declare @tabela as table (id int)
    while exists (select top 1 1 from [tabela_principal] where [condicao] )
    begin
    delete from @tabela
    insert into @tabela
    select top 10000 id from [tabela_principal]  (nolock) where [condicao]
    delete from [tabela_principal]  where id in (select id from @tabela)
    end

    Obrigada pela ajuda de todos!!!

    • Marcado como Resposta Helena Mam quinta-feira, 7 de novembro de 2013 18:57
    quinta-feira, 7 de novembro de 2013 18:57

Todas as Respostas

  • Helena, bom dia !

    A tabela onde voce vai fazer o delete tem quantos registros ? destes quantos voce vai deletar ? no filtro que voce vai utilizar no delete existe indice nestes campos ? se sim veja como esta a fragmentação dos mesmos, muitas vezes um rebuild nos indices ajuda bastante.

    Uma outra opção seria voce deixar o delete agendado para rodar no horario de menor movimento do site, normalmente durante a madrugada dependendo do site.


    Alexandre Matayosi Conde Mauricio.

    quarta-feira, 6 de novembro de 2013 13:28
  • Amigo,

    Tenta utilizando o rowcount. Eu tilizo para apagar grandes quantidades de  linhas, sem encher completamente o espaço livre em disco. Suspeito que a nível de performace deva ser é melhor, já que pula a etapa de ordenar.

    set rowcount 10000

    while exists (select 1 from [tabela]where [filtro])
    begin

    delete from [tabela] where [filtro]
    checkpoint

    end

    Abraço;

    quarta-feira, 6 de novembro de 2013 13:35
  • Olá Alexandre,

    Obrigada pelo retorno.

    Tenho 227.913.099 registros em uma das tabelas, preciso excluir torno de 200 milhões.

    Tenho um índice no campo id, que é exatamente o filtro que estou usando.

    Infelizmente, ainda não tenho a possibilidade de deletar esses registros em horário frio.

    Alguma sugestão?

    Obrigada.

    quarta-feira, 6 de novembro de 2013 13:46
  • Helena, uma sugestão seria voce ao inves de deletar os 200MM de registros voce inserir em outra tabela os pouco menos de 30MM que voce não vai deletar, tendo todos estes registros em outra tabela crie o indice nela e voce pode dropar a tabela original e depois alterar o nome da tabela que voce colocou os 30MM para o nome da tabela original, isto afetaria o seu sistema poucos segundos durante o processo de deletar a tabela e renomear a nova.

    Outra sugestão seria voce verificar criar um job recursivo que rodaria a cada X minutos e deletar uma quantidade de registros determinada cada vez que ele roda, faça um teste por exemplo de quantos registros ele deletaria em 30 segundos, a partir deste numero voce pode colocar o job para deletar somente esta quantidade de registros a cada 5 minutos por exemplo.


    Alexandre Matayosi Conde Mauricio.

    quarta-feira, 6 de novembro de 2013 14:12
  • Senhores,

    Achei uma solução para minha pergunta.

    Fiz uma query onde crio uma tabela temporária e a populo com 10000 registros, sendo esses apenas minha PK.

    Em seguida crio um laço onde verifico se existe os registros de acordo com a condição necessária. Após isso deleto da minha tabela principal os registros que estão na tabela temporária.

    Com essa query consegui deletar milhões de registros em poucos minutos, sem prejudicar a performance do site.

    Acho que ficou meio confuso, por isso, segue a query utilizada:

    set nocount on
    declare @tabela as table (id int)
    while exists (select top 1 1 from [tabela_principal] where [condicao] )
    begin
    delete from @tabela
    insert into @tabela
    select top 10000 id from [tabela_principal]  (nolock) where [condicao]
    delete from [tabela_principal]  where id in (select id from @tabela)
    end

    Obrigada pela ajuda de todos!!!

    • Marcado como Resposta Helena Mam quinta-feira, 7 de novembro de 2013 18:57
    quinta-feira, 7 de novembro de 2013 18:57