AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 243432
Accepted
vikrant rana
vikrant rana
Asked: 2019-07-23 01:12:05 +0800 CST2019-07-23 01:12:05 +0800 CST 2019-07-23 01:12:05 +0800 CST

ajustando a operação de exclusão enorme na tabela do sql server

  • 772

Estou executando uma operação de exclusão em uma tabela muito grande do servidor sql com base na consulta, conforme discutido abaixo.

delete db.st_table_1
where service_date between(select min(service_date) from stg_table)
                   and (select max(service_date) from stg_table);

stg_table e stg_table_1 não possuem índices em service_date.

ambas as tabelas são carregadas com milhões de linhas de dados e a operação de exclusão está demorando muito. Solicitando sua sugestão para melhorar o desempenho desta consulta.

Eu me referi à estratégia descrita na pergunta abaixo, mas não consegui entender como implementá-la.

Como excluir grande quantidade de dados no servidor sql sem perda de dados?

solicitando sua gentil sugestão sobre isso.

Atualizar:

select * into db.temp_stg_table_1
from db.stg_table_1
where service_date not between( select min(service_date) from db.stg_table)
                             and (select max(service_date) from db.stg_table);

exec sp_rename 'stg_table_1' , 'stg_table_1_old'

exec sp_rename 'temp_stg_table_1' , 'test_table_1'

drop table stg_table_1_old

que tal se ir com a lógica acima para excluir os milhões de registros. quaisquer vantagens e desvantagens com isso.

sql-server delete
  • 3 3 respostas
  • 2842 Views

3 respostas

  • Voted
  1. Best Answer
    Randi Vertongen
    2019-07-23T02:20:32+08:002019-07-23T02:20:32+08:00

    Testando com base em seus comentários

    Testado no SQL Server 2014 SP3

    stg_table e stg_table_1 não possuem índices em service_date.

    ambas as tabelas são carregadas com milhões de linhas de dados e a operação de exclusão está demorando muito.

    DDL

    CREATE TABLE dbo.st_table_1( stg_table_1_ID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
                                 service_date datetime2,
                                val  int)
    CREATE TABLE dbo.stg_table (stg_table_ID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
                                service_date datetime2,
                                val  int)
    

    PK's + Índices agrupados em campos de identidade.

    DML

    INSERT INTO dbo.stg_table WITH(TABLOCK)
    (
    service_date,val) 
    SELECT -- 1M
     DATEADD(S,rownum,GETDATE()),rownum
     FROM
     (SELECT TOP(1000000) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) as rownum
    FROM master.dbo.spt_values spt1
    CROSS APPLY master.dbo.spt_values spt2) as sptvalues
    
    INSERT INTO dbo.st_table_1 WITH(TABLOCK)
    (
    service_date,val) 
    SELECT -- 2.5M
     DATEADD(S,rownum,GETDATE()),rownum
     FROM
     (SELECT TOP(2500000) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) as rownum
    FROM master.dbo.spt_values spt1
    CROSS APPLY master.dbo.spt_values spt2) as sptvalues
    
    INSERT INTO dbo.stg_table WITH(TABLOCK)
    (
    service_date,val) 
    SELECT -- 4M
     DATEADD(S,rownum,GETDATE()),rownum
     FROM
     (SELECT TOP(4000000) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) as rownum
    FROM master.dbo.spt_values spt1
    CROSS APPLY master.dbo.spt_values spt2) as sptvalues
    

    2,5 milhões de linhas dbo.st_table_1e 5 milhões de linhas em dbo.stg_table (quase) todas essas 2,5 milhões de linhas serão excluídas pela consulta, que é mais de 10 vezes menor que a sua.

    Executando sua consulta

    O plano de execução real para sua instrução de exclusão básica

    Como esperado, dbo.stg_tableé acessado duas vezes para obter os valores máximo e mínimo com uma agregação de fluxo. O tempo de CPU e decorrido / tempo de execução:

      CPU time = 4906 ms,  elapsed time = 4919 ms.
    

    Uma dica de índice ausente é adicionada ao plano de execução:

    CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
    ON [dbo].[st_table_1] ([service_date])
    INCLUDE ([stg_table_1_ID])
    

    No entanto , quando adicionamos o índice, uma classificação extra aparece para excluir as linhas desse índice recém-adicionado:

    insira a descrição da imagem aqui

    O plano

    E o tempo de CPU / tempo decorrido aumenta:

       CPU time = 11156 ms,  elapsed time = 11332 ms.
    

    YMMV , mas no meu exemplo, com base em seus comentários sobre os dados, não melhorou a consulta.

    Criando um índice em [dbo].[stg_table]

    CREATE NONCLUSTERED INDEX IX_service_date
    ON [dbo].[stg_table] ([service_date]);
    

    Como resultado, o MAX()and MIN()pode aproveitar o índice recém-criado para retornar apenas uma linha em vez de uma verificação completa do índice clusterizado:

    insira a descrição da imagem aqui

    Com o tempo de execução melhorado:

     SQL Server Execution Times:
       CPU time = 2609 ms,  elapsed time = 4028 ms.
    

    E o plano de execução

    Mas isso é baseado apenas na indexação e no meu próprio exemplo. Prossiga por sua conta e risco.


    Notas Extras

    Você deve dividir essa exclusão em lotes separados para que ela não preencha o arquivo de log e não tenha um grande bloco de exclusão com falha / sucesso.

    Você também pode considerar usar (TABLOCK)para que toda a tabela esteja bloqueada desde o início.

    SET STATISTICS IO, TIME ON;
    delete dbo.st_table_1 WITH(TABLOCK)
    where service_date between(select min(service_date) from stg_table)
                       and (select max(service_date) from stg_table);
    

    Atualização: SELECT INTO+sp_rename

    select * into db.temp_stg_table_1
    from db.stg_table_1
    where service_date not between( select min(service_date) from db.stg_table)
                                 and (select max(service_date) from db.stg_table);
    
    exec sp_rename 'stg_table_1' , 'stg_table_1_old'
    
    exec sp_rename 'temp_stg_table_1' , 'test_table_1'
    
    drop table stg_table_1_old
    

    que tal se ir com a lógica acima para excluir os milhões de registros. quaisquer vantagens e desvantagens com isso.

    Além do desempenho, sp_renameprecisa de um Sch-Mbloqueio para ser concluído, o que significa que ele precisa esperar que todas as outras sessões liberem seus bloqueios na tabela antes de poder ser modificado. Quaisquer índices/restrições na tabela original desaparecerão e você terá que recriá-los.

    Quando executo a consulta em meus próprios dados:

    select * into dbo.temp_stg_table_1
    from dbo.st_table_1
    where service_date not between( select min(service_date) from dbo.stg_table)
                                 and (select max(service_date) from dbo.stg_table);
    

    Isso não representa seus dados, lembre-se disso.

    Ele está lendo todas as linhas para retornar 0, o que não é o ideal.

    insira a descrição da imagem aqui

    Com um alto tempo de execução:

     SQL Server Execution Times:
       CPU time = 27717 ms,  elapsed time = 10657 ms.
    

    Mas isso não é realmente significativo sem mais informações sobre seus dados. Um plano de consulta seria necessário para fornecer conselhos mais corretos.

    • 6
  2. Aaron Bertrand
    2019-07-24T09:24:04+08:002019-07-24T09:24:04+08:00

    Eu simplesmente nunca excluiria 37 milhões de linhas em uma instrução . Não se trata do plano de execução que você obtém - a sobrecarga de encontrar linhas para excluir (se você tem sniffing de parâmetro afetando a localização dessas linhas ou não) é muito menor do que a sobrecarga de realmente excluí-las e registrar essas exclusões. Se você dividir isso em partes, poderá amortizar esse custo ao longo do tempo e processar as exclusões em uma programação que seja adequada à sua fantasia, em vez de tudo de uma vez.

    -- you can play with these parameters to see what offers the best trade-off
    DECLARE @BatchSize int = 10000, @TransactionInterval tinyint = 5;
    
    DECLARE @s datetime, @e datetime, @r int = 1;
    
    SELECT @s = MIN(service_date), @e = MAX(service_date) FROM dbo.stg_table;
    
    BEGIN TRANSACTION;
    
    WHILE (@r > 0)
    BEGIN
      IF @r % @TransactionInterval = 1
      BEGIN
        COMMIT TRANSACTION;
        BEGIN TRANSACTION;
      END
    
      DELETE TOP (@BatchSize) FROM db.st_table_1
        WHERE service_date >= @s AND service_date <= @e;
    
      SET @r = @@ROWCOUNT;
    END
    
    IF @@TRANCOUNT > 0
    BEGIN
      COMMIT TRANSACTION;
    END
    

    Você também pode considerar a durabilidade atrasada se estiver em uma versão moderna o suficiente do SQL Server (consulte esta resposta e esta postagem de blog ).

    • 2
  3. KumarHarsh
    2019-07-23T04:01:19+08:002019-07-23T04:01:19+08:00

    A consulta acima pode funcionar bem devido ao índice ausente, mas a consulta ainda está errada.

    Declare @Fromdate DateTime
    Declare @Todate DateTime
    
    select @Fromdate=min(service_date),@Todate=max(service_date) 
    from dbo.stg_table
    
    SET STATISTICS IO, TIME ON;
    delete dbo.st_table_1 WITH(TABLOCK)
    where service_date >=@Fromdate
                      and service_date <=@Todate
    

    Peguei o exemplo acima e executei sem Index, demorou 18 segundos para excluir 410792 linhas.

    Se eu criar o Index como acima, sem dúvidas, ele terá o melhor desempenho.

    1. Portanto, não Sub Queryem Wherecondições, pode dar High Cardianility Estimateem consulta complexa.
    2. Dê mais importância por escrito Optimize querydo que index.Ambos são importantes.

    Observação :

    Se o desempenho for ruim ou pior por causa Parameter Sniffingdisso, você deve encontrar uma maneira adequada de evitar Parameter sniffing, caso contrário, você deve IGNORÁ-lo.

    Afinal nem tudo Store Procedureé escrito com OPTION RECOMPILE.

    Pelo que entendi, no meu script @FromDatee @Todatenão são parâmetros proc, são variáveis ​​locais, então não há dúvida de Parameter Sniffing.

    • 0

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve