sql-server – 为什么DELETE会对性能产生影响?

最后是一个测试脚本,用于比较@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(又名GetDate())是在语句时而不是批处理中进行的,因此TRUNCATE / DELETE与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,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,CURRENT_TIMESTAMP) 
    SET @i +=  1 
  END -- WHILE 

SELECT DurationInMilliseconds = Duration FROM   @ExecutionTime 
GO

DROP TABLE  #values 
SET NOCOUNT OFF;

解决方法

当对象是B树时,这种差异似乎只适用.删除表变量上的主键,因此它是一个堆,我得到了以下结果
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树进行批量插入时,存在一些可用的优化,仅在它尚未分配任何页面时才适用.

我基于以下观察结果.

>运行各种版本的测试代码时,我只看到了@table_variables和#temp表的这种模式.不是tempdb中的永久表,也不是##表.
>为了获得较慢的性能,不必先从表中添加和删除大量行.只需添加一行并将其留在那里即可.
> TRUNCATE从表中取消分配所有页面. DELETE不会导致表中的最后一页被释放.
>使用VS 2012探查器显示,在更快的情况下,SQL Server使用不同的代码路径. 36%的时间花在sqlmin.dll!RowsetBulk :: InsertRow vs sqlmin.dll花费的时间的61%!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 |
+-------------+------------+--------------+--------------------+

我发现有可能在enabling trace flag 610之间减少时间差异.

这样可以大大减少后续插入的日志记录量(从350 MB减少到103 MB,因为它不再记录单个插入的行值),但这对第二次和后续的@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).

值得注意的是,这些更快的插入只有657个事务(LOP_BEGIN_XACT / LOP_COMMIT_XACT对),而在较慢的情况下超过10,000.特别是LOP_FORMAT_PAGE操作似乎大大减少了.对于表中的每个页面(约10,270),较慢的情况具有针对此的事务日志条目,而在快速情况下仅有4个这样的条目.

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

记录针对@table_var的第一个插入(96.5 MB)

记录后续插入TF 610关闭(350 MB)

记录后续插入TF 610(103 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 | 25
2560
2120
2080
2130
2140
2560 2120 2080 2130 2140|
| 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 |
+-----------------------+----------+----------------------------------------------+---------------+---------+
+-----------------------+--------------------+----------------------------------------------+---------------+---------+ | 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 | 25
2560
2120
2080
2130
2140
2560 2120 2080 2130 2140|
| 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 |
+-----------------------+--------------------+----------------------------------------------+---------------+---------+
+-------------------------+-------------------------+----------------------------------------------+---------------+---------+ | 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 | +-------------------------+-------------------------+----------------------------------------------+---------------+---------+

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


本篇内容主要讲解“sqlalchemy的常用数据类型怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“sqlalche...
今天小编给大家分享一下sqlServer实现分页查询的方式有哪些的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家
这篇文章主要介绍“sqlmap之osshell怎么使用”,在日常操作中,相信很多人在sqlmap之osshell怎么使用问题上存在疑惑,小编查阅了各式资料,整理出
本篇内容介绍了“SQL注入的知识点有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧...
1. mssql权限sa权限:数据库操作,文件管理,命令执行,注册表读取等system。是mssql的最高权限db权限:文件管理,数据库操作等 users-administratorspublic权限:数据库操作 guest-users2、sql server注入执行命令查
sql执行计划如何查看?在SPL庞大的数据中我们不知道如何查看实际数据库中发生了什么事情,有必要定期进行查询优化和索引否则会影响我们后期的SQL的查询速度。那么针对这样的问题我们必须要知道SQL执行的计划,在本文中winwin7小编给大家分享下SQL执
SQL Server 是Microsoft 公司推出的关系型数据库管理系统。具有使用方便可伸缩性好与相关软件集成程度高等优点应用非常广泛。不过在使用中,我们会遇到非常多的错误,面对这么庞大的数据库环境,当然会有精确的错误代码的对照季,下面小编分享的
SQL Server本地账户无法登陆出现错误提示:error:40-Could not open a connenction to SQL Server的问题很常见,对于初学者来说可能不知道如何解决,一起来看看下面的解决方案。解决步骤如下:1、这种情况需要开启 SQL Server service
微软推出的SQL2008是一款非常好用的数据库软件,它稳定、功能强大,为众多企业提供了最佳的数据库解决方案,那么我们如何在Windows中安装它呢,一些朋友对SQL Server 2008的安装过程还不是很熟悉,下面就一起来看看SQL Server 2008详细安装图解...
本页概要如果您使用的是 SQL Server 2005备份和还原Sp_detach_db 和 Sp_attach_db 存储过程关于排序规则的说明导入和导出数据(在 SQL Server 数据库之间复
DBCC CHECKIDENT 检查指定表的当前标识值,如有必要,还对标识值进行更正。 语法 DBCC CHECKIDENT ( &#39;table_name&#39; [ , { NORESEED
这里对 SQL Server 字符串函数进行分门别类地列出,便于查阅和记忆,相信大家都在其它方面有高深的编程基础,从字面上来说大家都知道这些函数的意义,就不对这些函数作过多的解释了,主要谈些经验,具体
查询及删除重复记录的方法 1、查找表(people)中多余的重复记录,重复记录是根据单个字段(peopleId)来判断select*frompeoplewherepeopleIdin(selectpe
微软发SQL Server 2008第二个CTP预览版from: http://news.csdn.net/n/20070807/107158.html8月7日消息,微软公司本周发布了SQL Serv
症状当您将数据库备份恢复到另一台服务器时,可能会遇到孤立用户的问题。SQL Server 联机丛书中的孤立用户疑难解答主题中没有讲述解决此问题的具体步骤。本文介绍了如何解决孤立用户问题。更多信息虽然术
当登录SQL Server 2005时可能碰到错误: &#39;No Process is on the Other End of the Pipe&#39;。解决方法:(1)Open up SQL
概要本文描述如何映射标准登录和集成登录来解决在运行 SQL Server 的服务器之间移动数据库时的权限问题。更多信息当您将数据库从一个运行 SQL Server 的服务器移到另一个运行 SQL Se
----------------------------------------问题:该用户与可信的SQL SERVER 连接无关联使用sa用户或自建用户使用“SQL SERVER 身份认证”连接数据
更新日期: 2007 年 5 月 20 日 使用下表可以确定各种版本的 Microsoft SQL Server 2005 支持哪些功能。有关 SQL Server 2005 Enterprise E
当从Excel导入数据到Sql Sever中,可能会出现以下问题:&#xD;&#xA;对于指定的缓冲区大小而言,源列的数据太大