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 / 27309
Accepted
孔夫子
孔夫子
Asked: 2012-10-21 12:36:26 +0800 CST2012-10-21 12:36:26 +0800 CST 2012-10-21 12:36:26 +0800 CST

Por que DELETE deixa um efeito prolongado no desempenho?

  • 772

No final, há um script de teste para comparar o desempenho entre uma variável @table e uma tabela #temp. Acho que configurei corretamente - os tempos de desempenho são retirados dos comandos DELETE/TRUNCATE . Os resultados que estou obtendo são os seguintes (tempos em milissegundos).

@Table Variable  #Temp (delete)  #Temp (truncate)
---------------  --------------  ----------------
5723             5180            5506
15636            14746           7800
14506            14300           5583
14030            15460           5386
16706            16186           5360

Só para ter certeza de que estou são, isso mostra que CURRENT_TIMESTAMP (também conhecido como GetDate()) é obtido no momento da instrução, não do lote, portanto, não deve haver interação entre TRUNCATE/DELETE com a SET @StartTime = CURRENT_TIMESTAMPinstrução.

select current_timestamp
waitfor delay '00:00:04'
select current_timestamp

-----------------------
2012-10-21 11:29:20.290

-----------------------
2012-10-21 11:29:24.290

É bastante consistente no salto entre a primeira execução e as subsequentes quando DELETE é usado para limpar a tabela. O que estou perdendo em minha compreensão de DELETE ? Eu repeti isso muitas vezes, troquei a ordem, dimensionei o tempdb para não exigir crescimento, etc.

CREATE TABLE #values (
  id int identity primary key, -- will be clustered
  name varchar(100) null,
  number int null,
  type char(3) not null,
  low int null,
  high int null,
  status smallint not null
);
GO
SET NOCOUNT ON;

DECLARE @values TABLE (
  id int identity primary key clustered,
  name varchar(100) null,
  number int null,
  type char(3) not null,
  low int null,
  high int null,
  status smallint not null
);
DECLARE  @ExecutionTime  TABLE(      Duration bigINT    ) 
DECLARE  @StartTime DATETIME,  @i INT = 1; 
WHILE (@i <= 5) 
  BEGIN 
    DELETE @values;
    DBCC freeproccache With NO_InfoMSGS;
    DBCC DROPCLEANBUFFERS With NO_InfoMSGS;
    SET @StartTime = CURRENT_TIMESTAMP -- alternate getdate() 
    /****************** measured process ***********************/ 

    INSERT @values SELECT a.* FROM master..spt_values a join master..spt_values b on b.type='P' and b.number < 1000;

    /**************** end measured process *********************/ 
    INSERT @ExecutionTime 
    SELECT DurationInMilliseconds = datediff(ms,@StartTime,CURRENT_TIMESTAMP) 
    SET @i +=  1 
  END -- WHILE 

SELECT DurationInMilliseconds = Duration FROM   @ExecutionTime 
GO 

-- Temporary table
DECLARE  @ExecutionTime  TABLE(      Duration bigINT    ) 
DECLARE  @StartTime DATETIME,  @i INT = 1; 
WHILE (@i <= 5) 
  BEGIN 
    delete #values;
    -- TRUNCATE TABLE #values;
    DBCC freeproccache With NO_InfoMSGS;
    DBCC DROPCLEANBUFFERS With NO_InfoMSGS;
    SET @StartTime = CURRENT_TIMESTAMP -- alternate getdate() 
    /****************** measured process ***********************/ 

    INSERT #values SELECT a.* FROM master..spt_values a join master..spt_values b on b.type='P' and b.number < 1000;

    /**************** end measured process *********************/ 
    INSERT @ExecutionTime 
    SELECT DurationInMilliseconds = datediff(ms,@StartTime,CURRENT_TIMESTAMP) 
    SET @i +=  1 
  END -- WHILE 

SELECT DurationInMilliseconds = Duration FROM   @ExecutionTime 
GO

DROP TABLE  #values 
SET NOCOUNT OFF;
sql-server performance
  • 2 2 respostas
  • 4223 Views

2 respostas

  • Voted
  1. Best Answer
    Martin Smith
    2012-10-21T16:08:35+08:002012-10-21T16:08:35+08:00

    Essa diferença só parece se aplicar quando o objeto é uma árvore B+. Ao remover a primary keyvariável da tabela para que seja um heap, obtive os seguintes resultados

    2560
    2120
    2080
    2130
    2140
    

    Mas com o PK encontrei um padrão semelhante em meus testes também com resultados típicos abaixo.

    +--------+--------+---------+-------------------+
    | @table | #table | ##table | [permanent_table] |
    +--------+--------+---------+-------------------+
    |   2670 |   2683 |    9603 |              9703 |
    |   6823 |   6840 |    9723 |              9790 |
    |   6813 |   6816 |    9626 |              9703 |
    |   6883 |   6816 |    9600 |              9716 |
    |   6840 |   6856 |    9610 |              9673 |
    +--------+--------+---------+-------------------+
    

    Minha teoria é que há alguma otimização disponível ao fazer inserções em massa em árvores B+ temporárias locais que só se aplica quando ainda não possui nenhuma página alocada.

    Baseio-me nas seguintes observações.

    1. Ao executar várias versões do seu código de teste, só vi esse padrão com tabelas @table_variablese . #tempNão são tabelas permanentes tempdbnem ##tabelas.

    2. Para obter o desempenho mais lento, não é necessário ter adicionado e removido anteriormente uma grande quantidade de linhas da tabela. Simplesmente adicionar uma única linha e deixá-la lá é suficiente.

    3. TRUNCATEdesaloca todas as páginas da tabela. DELETEnão fará com que a última página da tabela seja desalocada.

    4. O uso do criador de perfil do VS 2012 mostra que, no caso mais rápido, o SQL Server usa um caminho de código diferente. 36% do tempo é gasto em sqlmin.dll!RowsetBulk::InsertRowvs 61% do tempo gasto no sqlmin.dll!RowsetNewSS::InsertRowcaso mais lento.

    Corrida

    SELECT * 
    FROM sys.dm_db_index_physical_stats(2,OBJECT_ID('tempdb..#values'),1,NULL, 'DETAILED')
    

    depois que a exclusão retorna

    +-------------+------------+--------------+--------------------+
    | index_level | page_count | record_count | ghost_record_count |
    +-------------+------------+--------------+--------------------+
    |           0 |          1 |            0 |                  1 |
    |           1 |          1 |            1 |                  0 |
    |           2 |          1 |            1 |                  0 |
    +-------------+------------+--------------+--------------------+
    

    Descobri que era possível reduzir um pouco a discrepância de tempo ativando o sinalizador de rastreamento 610 .

    Isso teve o efeito de reduzir substancialmente a quantidade de registros para as inserções subsequentes (de 350 MB para 103 MB, já que não registra mais os valores individuais das linhas inseridas), mas teve apenas uma pequena melhoria nos tempos para o segundo e @tablesubsequentes #tablecasos e a lacuna ainda permanece. O sinalizador de rastreamento melhorou significativamente o desempenho geral das inserções nos outros dois tipos de tabela.

    +--------+--------+---------+-------------------+
    | @table | #table | ##table | [permanent_table] |
    +--------+--------+---------+-------------------+
    |   2663 |   2670 |    5403 |              5426 |
    |   5390 |   5396 |    5410 |              5403 |
    |   5373 |   5390 |    5410 |              5403 |
    |   5393 |   5410 |    5406 |              5433 |
    |   5386 |   5396 |    5390 |              5420 |
    +--------+--------+---------+-------------------+
    

    Ao examinar o log de transações, notei que as inserções iniciais em tabelas temporárias locais vazias parecem ainda mais minimamente registradas (em 96 MB).

    Notavelmente, essas inserções mais rápidas tinham apenas 657transações ( LOP_BEGIN_XACT/ LOP_COMMIT_XACTpares) em comparação com 10,000os casos mais lentos. Em particular LOP_FORMAT_PAGE, as operações parecem muito reduzidas. Os casos mais lentos têm uma entrada de log de transação para cada página na tabela (cerca de 10,270) em comparação com apenas 4essas entradas no caso rápido.

    O log usado em todos os três casos foi o seguinte (excluí os registros de log para atualizações nas tabelas base do sistema para reduzir a quantidade de texto, mas eles ainda estão incluídos nos totais)

    Registrando a primeira inserção contra @table_var(96,5 MB)

    +-----------------------+----------+----------------------------------------------+---------------+---------+
    |       Operation       | Context  |                AllocUnitName                 | Size in Bytes |   Cnt   |
    +-----------------------+----------+----------------------------------------------+---------------+---------+
    | LOP_BEGIN_XACT        | LCX_NULL | NULL                                         |         83876 |     658 |
    | LOP_COMMIT_XACT       | LCX_NULL | NULL                                         |         34164 |     657 |
    | LOP_CREATE_ALLOCCHAIN | LCX_NULL | NULL                                         |           120 |       3 |
    | LOP_FORMAT_PAGE       | LCX_HEAP | dbo.#531856C7                                |            84 |       1 |
    | LOP_FORMAT_PAGE       | LCX_IAM  | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |            84 |       1 |
    | LOP_FORMAT_PAGE       | LCX_IAM  | dbo.#531856C7                                |            84 |       1 |
    | LOP_FORMAT_PAGE       | LCX_IAM  | Unknown Alloc Unit                           |            84 |       1 |
    | LOP_HOBT_DDL          | LCX_NULL | NULL                                         |           216 |       6 |
    | LOP_HOBT_DELTA        | LCX_NULL | NULL                                         |           320 |       5 |
    | LOP_IDENT_NEWVAL      | LCX_NULL | NULL                                         |     100240000 | 2506000 |
    | LOP_INSERT_ROWS       | LCX_HEAP | dbo.#531856C7                                |            72 |       1 |
    | LOP_MODIFY_ROW        | LCX_IAM  | dbo.#531856C7                                |            88 |       1 |
    | LOP_MODIFY_ROW        | LCX_PFS  | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |        158592 |    1848 |
    | LOP_MODIFY_ROW        | LCX_PFS  | dbo.#531856C7                                |            80 |       1 |
    | LOP_MODIFY_ROW        | LCX_PFS  | Unknown Alloc Unit                           |        216016 |    2455 |
    | LOP_SET_BITS          | LCX_GAM  | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |         84360 |    1406 |
    | LOP_SET_BITS          | LCX_GAM  | Unknown Alloc Unit                           |        147120 |    2452 |
    | LOP_SET_BITS          | LCX_IAM  | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |         84360 |    1406 |
    | LOP_SET_BITS          | LCX_IAM  | Unknown Alloc Unit                           |        147120 |    2452 |
    | Total                 | NULL     | NULL                                         |     101209792 | 2519475 |
    +-----------------------+----------+----------------------------------------------+---------------+---------+
    

    Registrando inserções subseqüentes TF 610 off (350 MB)

    +-----------------------+--------------------+----------------------------------------------+---------------+---------+
    |       Operation       |      Context       |                AllocUnitName                 | Size in Bytes |   Cnt   |
    +-----------------------+--------------------+----------------------------------------------+---------------+---------+
    | LOP_BEGIN_CKPT        | LCX_NULL           | NULL                                         |            96 |       1 |
    | LOP_BEGIN_XACT        | LCX_NULL           | NULL                                         |       1520696 |   12521 |
    | LOP_COMMIT_XACT       | LCX_NULL           | NULL                                         |        651040 |   12520 |
    | LOP_CREATE_ALLOCCHAIN | LCX_NULL           | NULL                                         |            40 |       1 |
    | LOP_DELETE_SPLIT      | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |          2160 |      36 |
    | LOP_END_CKPT          | LCX_NULL           | NULL                                         |           136 |       1 |
    | LOP_FORMAT_PAGE       | LCX_HEAP           | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |        859236 |   10229 |
    | LOP_FORMAT_PAGE       | LCX_IAM            | Unknown Alloc Unit                           |            84 |       1 |
    | LOP_FORMAT_PAGE       | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |          3108 |      37 |
    | LOP_HOBT_DDL          | LCX_NULL           | NULL                                         |           648 |      18 |
    | LOP_HOBT_DELTA        | LCX_NULL           | NULL                                         |        657088 |   10267 |
    | LOP_IDENT_NEWVAL      | LCX_NULL           | NULL                                         |     100239960 | 2505999 |
    | LOP_INSERT_ROWS       | LCX_CLUSTERED      | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |     258628000 | 2506000 |
    | LOP_INSERT_ROWS       | LCX_HEAP           | dbo.#531856C7                                |            72 |       1 |
    | LOP_INSERT_ROWS       | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |       1042776 |   10302 |
    | LOP_MODIFY_HEADER     | LCX_HEAP           | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |        859236 |   10229 |
    | LOP_MODIFY_HEADER     | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |          3192 |      38 |
    | LOP_MODIFY_ROW        | LCX_IAM            | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |           704 |       8 |
    | LOP_MODIFY_ROW        | LCX_PFS            | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |        934264 |   11550 |
    | LOP_MODIFY_ROW        | LCX_PFS            | Unknown Alloc Unit                           |        783984 |    8909 |
    | LOP_SET_BITS          | LCX_GAM            | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |         76980 |    1283 |
    | LOP_SET_BITS          | LCX_GAM            | Unknown Alloc Unit                           |        534480 |    8908 |
    | LOP_SET_BITS          | LCX_IAM            | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 |         76980 |    1283 |
    | LOP_SET_BITS          | LCX_IAM            | Unknown Alloc Unit                           |        534480 |    8908 |
    | LOP_SHRINK_NOOP       | LCX_NULL           | NULL                                         |            32 |       1 |
    | LOP_XACT_CKPT         | LCX_NULL           | NULL                                         |            92 |       1 |
    | Total                 | NULL               | NULL                                         |     367438748 | 5119297 |
    +-----------------------+--------------------+----------------------------------------------+---------------+---------+
    

    Registrando inserções subsequentes TF 610 em (103 MB)

    +-------------------------+-------------------------+----------------------------------------------+---------------+---------+
    |        Operation        |         Context         |                AllocUnitName                 | Size in Bytes |   Cnt   |
    +-------------------------+-------------------------+----------------------------------------------+---------------+---------+
    | LOP_BEGIN_CKPT          | LCX_NULL                | NULL                                         |           192 |       2 |
    | LOP_BEGIN_XACT          | LCX_NULL                | NULL                                         |       1339796 |   11099 |
    | LOP_BULK_EXT_ALLOCATION | LCX_NULL                | NULL                                         |         20616 |     162 |
    | LOP_COMMIT_XACT         | LCX_NULL                | NULL                                         |        577096 |   11098 |
    | LOP_CREATE_ALLOCCHAIN   | LCX_NULL                | NULL                                         |            40 |       1 |
    | LOP_DELETE_SPLIT        | LCX_INDEX_INTERIOR      | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |          2160 |      36 |
    | LOP_END_CKPT            | LCX_NULL                | NULL                                         |           272 |       2 |
    | LOP_FORMAT_PAGE         | LCX_BULK_OPERATION_PAGE | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |        863520 |   10280 |
    | LOP_FORMAT_PAGE         | LCX_IAM                 | Unknown Alloc Unit                           |            84 |       1 |
    | LOP_FORMAT_PAGE         | LCX_INDEX_INTERIOR      | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |          3108 |      37 |
    | LOP_HOBT_DELTA          | LCX_NULL                | NULL                                         |        666496 |   10414 |
    | LOP_IDENT_NEWVAL        | LCX_NULL                | NULL                                         |     100239960 | 2505999 |
    | LOP_INSERT_ROWS         | LCX_CLUSTERED           | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |         23544 |     218 |
    | LOP_INSERT_ROWS         | LCX_HEAP                | dbo.#719CDDE7                                |            72 |       1 |
    | LOP_INSERT_ROWS         | LCX_INDEX_INTERIOR      | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |       1042776 |   10302 |
    | LOP_MODIFY_HEADER       | LCX_BULK_OPERATION_PAGE | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |        780216 |   10266 |
    | LOP_MODIFY_HEADER       | LCX_HEAP                | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |       1718472 |   20458 |
    | LOP_MODIFY_HEADER       | LCX_INDEX_INTERIOR      | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |          3192 |      38 |
    | LOP_MODIFY_ROW          | LCX_IAM                 | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |           704 |       8 |
    | LOP_MODIFY_ROW          | LCX_PFS                 | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |        114832 |    1307 |
    | LOP_MODIFY_ROW          | LCX_PFS                 | Unknown Alloc Unit                           |        231696 |    2633 |
    | LOP_RANGE_INSERT        | LCX_NULL                | NULL                                         |            48 |       1 |
    | LOP_SET_BITS            | LCX_GAM                 | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |         77100 |    1285 |
    | LOP_SET_BITS            | LCX_GAM                 | Unknown Alloc Unit                           |        157920 |    2632 |
    | LOP_SET_BITS            | LCX_IAM                 | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 |         77100 |    1285 |
    | LOP_SET_BITS            | LCX_IAM                 | Unknown Alloc Unit                           |        157920 |    2632 |
    | LOP_XACT_CKPT           | LCX_NULL                | NULL                                         |            92 |       1 |
    | Total                   | NULL                    | NULL                                         |     108102960 | 2602218 |
    +-------------------------+-------------------------+----------------------------------------------+---------------+---------+
    
    • 20
  2. Mike Sherrill 'Cat Recall'
    2012-10-21T14:15:32+08:002012-10-21T14:15:32+08:00

    Observação e especulação. . .

    Em alguns sistemas, CURRENT_TIMESTAMP é definido como a hora de início da transação atual. Uma pesquisa rápida não revelou nenhuma documentação definitiva de como CURRENT_TIMESTAMP se comporta no SQL Server. Mas o modo padrão do SQL Server é confirmar transações automaticamente, e não há BEGIN TRANSACTION aqui, então deve ser o tempo imediatamente antes da instrução INSERT. (A instrução DELETE deve ser confirmada automaticamente e, independentemente da maneira como CURRENT_TIMESTAMP funcione no SQL Server, não deve ter nada a ver com a instrução DELETE quando você estiver usando transações confirmadas automaticamente.)

    Na primeira iteração, a instrução DELETE não tem nenhum trabalho real a fazer e não há nenhuma linha individual para registrar. Talvez o otimizador saiba disso e esteja reduzindo o tempo da primeira iteração. (A combinação de nenhuma linha para excluir e nenhuma linha individual para registrar.)

    Você poderia testar isso (eu acho) inserindo antes de excluir.

    • 0

relate perguntas

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

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

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

Sidebar

Stats

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

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 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

    Como selecionar a primeira linha de cada grupo?

    • 6 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +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