AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 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

为什么 DELETE 会对性能产生挥之不去的影响?

  • 772

最后是一个测试脚本,用于比较@table 变量和#temp 表之间的性能。我想我已经正确设置了——性能计时是在 DELETE/TRUNCATE 命令之外进行的。我得到的结果如下(以毫秒为单位)。

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

只是为了确保我是理智的,这表明 CURRENT_TIMESTAMP (aka ) 是在语句时获取的,而不是批处理时,因此 TRUNCATE/DELETE 与语句GetDate()之间应该没有交互。SET @StartTime = CURRENT_TIMESTAMP

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

当使用DELETE清表时,第一次运行和后续运行之间的跳转是相当一致的。我对DELETE的理解缺少什么?我已经重复了很多次,交换了顺序,将 tempdb 调整为不需要增长等。

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 个回答
  • 4223 Views

2 个回答

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

    这种差异似乎只适用于对象是 B+树的情况。当删除primary key表变量时,它是一个堆,我得到了以下结果

    2560
    2120
    2080
    2130
    2140
    

    但是对于 PK,我在测试中也发现了类似的模式,典型的结果如下。

    +--------+--------+---------+-------------------+
    | @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 |
    +--------+--------+---------+-------------------+
    

    我的理论是,在对本地临时 B+ 树进行批量插入时,有一些优化可用,这些优化仅适用于尚未分配任何页面的情况。

    我基于以下观察。

    1. 在运行各种版本的测试代码时,我只看到了这种模式@table_variables和#temp表格。tempdb也不是表中的永久##表。

    2. 为了获得较慢的性能,不必事先从表中添加和删除大量行。只需添加一行并将其保留在那里就足够了。

    3. TRUNCATE从表中释放所有页。DELETE不会导致表中的最后一页被释放。

    4. 使用 VS 2012 分析器表明,在更快的情况下 SQL Server 使用不同的代码路径。36% 的时间花在了较慢的情况下sqlmin.dll!RowsetBulk::InsertRow,而 61% 的时间花在sqlmin.dll!RowsetNewSS::InsertRow了较慢的情况下。

    跑步

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

    删除返回后

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

    我发现通过启用跟踪标志 610可以在一定程度上减少时间差异。

    这具有显着减少后续插入的日志记录数量的效果(从 350 MB 下降到 103 MB,因为它不再记录单个插入的行值),但这对第 2 次和后续情况@table的计时只有很小的改进#table差距仍然存在。跟踪标志显着提高了插入其他两种表类型的一般性能。

    +--------+--------+---------+-------------------+
    | @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 |
    +--------+--------+---------+-------------------+
    

    通过查看事务日志,我注意到针对空本地临时表的初始插入似乎记录得更少(96 MB)。

    值得注意的是,与较慢情况下的 over 相比,这些较快的插入只有657事务(LOP_BEGIN_XACT/对)。特别是操作似乎大大减少。较慢的情况对于表中的每个页面都有一个事务日志条目(大约),而在快速情况下只有这样的条目。LOP_COMMIT_XACT10,000LOP_FORMAT_PAGE10,2704

    这三种情况下使用的日志如下(我已经删除了更新系统基表的日志记录以减少文本量,但它们仍然包含在总数中)

    记录第一次插入@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 |
    +-----------------------+----------+----------------------------------------------+---------------+---------+
    

    记录后续插入 TF 610 关闭 (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 |
    +-----------------------+--------------------+----------------------------------------------+---------------+---------+
    

    记录后续插入 TF 610 (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

    观察和推测。. .

    在某些系统上,CURRENT_TIMESTAMP 被定义为当前事务开始的时间。快速搜索发现没有关于 CURRENT_TIMESTAMP 在 SQL Server 上的行为的明确文档。但是SQL Server的默认模式是自动提交事务,这里没有BEGIN TRANSACTION,所以应该是INSERT语句之前的时间。(DELETE 语句应该自动提交,无论 CURRENT_TIMESTAMP 在 SQL Server 上以哪种方式工作,当您使用自动提交的事务时,它都不应该与 DELETE 语句有任何关系。)

    在第一次迭代中,DELETE 语句没有任何实际工作要做,也没有任何单独的行要记录。也许优化器知道这一点,这减少了第一次迭代的时间。(没有要删除的行,也没有要记录的单个行的组合。)

    您可以通过在删除之前插入来测试(我认为)。

    • 0

相关问题

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何查看 Oracle 中的数据库列表?

    • 8 个回答
  • Marko Smith

    mysql innodb_buffer_pool_size 应该有多大?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    从 .frm 和 .ibd 文件恢复表?

    • 10 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST

热门标签

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

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve