加入收藏 | 设为首页 | 会员中心 | 我要投稿 青岛站长网 (https://www.0532zz.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

sql-server – 在这种特定情况下,为什么使用表变量的速度是#temp

发布时间:2020-12-24 22:16:30 所属栏目:MsSql教程 来源:网络整理
导读:我在看这篇文章 Temporary Tables vs. Table Variables and Their Effect on SQL Server Performance和SQL Server 2008能够再现与2005年那里显示的结果类似的结果. 当执行只有10行的存储过程(下面的定义)时,表变量版本out执行临时表版本的次数超过两次. 我清

在另一个连接中轮询sys.dm_os_waiting_tasks

CREATE TABLE #T(resource_description NVARCHAR(2048))

WHILE 1=1
INSERT INTO #T
SELECT resource_description
FROM sys.dm_os_waiting_tasks
WHERE session_id=<spid_of_other_session> and wait_type='PAGELATCH_SH'

离开运行约15秒后,它收集了以下结果

+-------+----------------------+
| Count | resource_description |
+-------+----------------------+
|  1098 | 2:1:150              |
|  1689 | 2:1:146              |
+-------+----------------------+

这两个被锁存的页面都属于名为’nc1’和’nc2’的tempdb.sys.sysschobjs基表上的(不同的)非聚簇索引.

在运行期间查询tempdb.sys.fn_dblog表示由第一次执行每个存储过程添加的日志记录的数量有些变化,但对于后续执行,每次迭代添加的数量非常一致且可预测.缓存过程计划后,日志条目的数量大约是#temp版本所需的一半.

+-----------------+----------------+------------+
|                 | Table Variable | Temp Table |
+-----------------+----------------+------------+
| First Run       |            126 | 72 or 136  |
| Subsequent Runs |             17 | 32         |
+-----------------+----------------+------------+

查看SP的#temp表版本的事务日志条目,每次后续调用存储过程都会创建三个事务,而表变量只有两个.

+---------------------------------+----+---------------------------------+----+
|           #Temp Table                |         @Table Variable              |
+---------------------------------+----+---------------------------------+----+
| CREATE TABLE                    |  9 |                                 |    |
| INSERT                          | 12 | TVQuery                         | 12 |
| FCheckAndCleanupCachedTempTable | 11 | FCheckAndCleanupCachedTempTable |  5 |
+---------------------------------+----+---------------------------------+----+

除名称外,INSERT / TVQUERY事务是相同的.它包含插入临时表或表变量的10行中的每一行的日志记录以及LOP_BEGIN_XACT / LOP_COMMIT_XACT条目.

CREATE TABLE事务仅出现在#Temp版本中,如下所示.

+-----------------+-------------------+---------------------+
|    Operation    |      Context      |    AllocUnitName    |
+-----------------+-------------------+---------------------+
| LOP_BEGIN_XACT  | LCX_NULL          |                     |
| LOP_SHRINK_NOOP | LCX_NULL          |                     |
| LOP_MODIFY_ROW  | LCX_CLUSTERED     | sys.sysschobjs.clst |
| LOP_DELETE_ROWS | LCX_MARK_AS_GHOST | sys.sysschobjs.nc1  |
| LOP_INSERT_ROWS | LCX_INDEX_LEAF    | sys.sysschobjs.nc1  |
| LOP_DELETE_ROWS | LCX_MARK_AS_GHOST | sys.sysschobjs.nc2  |
| LOP_INSERT_ROWS | LCX_INDEX_LEAF    | sys.sysschobjs.nc2  |
| LOP_MODIFY_ROW  | LCX_CLUSTERED     | sys.sysschobjs.clst |
| LOP_COMMIT_XACT | LCX_NULL          |                     |
+-----------------+-------------------+---------------------+

FCheckAndCleanupCachedTempTable事务同时出现在#temp版本中,但有6个附加条目.这些是指向sys.sysschobjs的6行,它们具有与上面完全相同的模式.

+-----------------+-------------------+----------------------------------------------+
|    Operation    |      Context      |                AllocUnitName                 |
+-----------------+-------------------+----------------------------------------------+
| LOP_BEGIN_XACT  | LCX_NULL          |                                              |
| LOP_DELETE_ROWS | LCX_NONSYS_SPLIT  | dbo.#7240F239.PK__#T________3BD0199374293AAB |
| LOP_HOBT_DELTA  | LCX_NULL          |                                              |
| LOP_HOBT_DELTA  | LCX_NULL          |                                              |
| LOP_MODIFY_ROW  | LCX_CLUSTERED     | sys.sysschobjs.clst                          |
| LOP_DELETE_ROWS | LCX_MARK_AS_GHOST | sys.sysschobjs.nc1                           |
| LOP_INSERT_ROWS | LCX_INDEX_LEAF    | sys.sysschobjs.nc1                           |
| LOP_DELETE_ROWS | LCX_MARK_AS_GHOST | sys.sysschobjs.nc2                           |
| LOP_INSERT_ROWS | LCX_INDEX_LEAF    | sys.sysschobjs.nc2                           |
| LOP_MODIFY_ROW  | LCX_CLUSTERED     | sys.sysschobjs.clst                          |
| LOP_COMMIT_XACT | LCX_NULL          |                                              |
+-----------------+-------------------+----------------------------------------------+

在两个事务中查看这6行,它们对应于相同的操作.第一个LOP_MODIFY_ROW,LCX_CLUSTERED是sys.objects中modify_date列的更新.剩下的五行都与对象重命名有关.因为name是受影响的NCI(nc1和nc2)的一个关键列,所以它作为删除/插入执行,然后它返回到聚簇索引并更新它.

(编辑:青岛站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读