为什么临时表的RowSetSharing在存储过程中不起作用?

时间:2018-03-02 12:55:38

标签: sql-server sqlperformance

以下是一个例子:

context.getRemainingTimeInMillis()

运行它并检查等待统计信息:

CREATE TABLE #t
(
    id int IDENTITY(1,1) PRIMARY KEY,
    ss varchar(50)
)

INSERT INTO #t (ss)
    SELECT name FROM master.dbo.spt_values

DELETE FROM #t
SELECT * FROM sys.dm_exec_session_wait_stats WHERE session_id = <spid>

现在在存储过程中放入相同的代码:

session_id wait_type                      waiting_tasks_count  wait_time_ms         max_wait_time_ms     signal_wait_time_ms
---------- ------------------------------ -------------------- -------------------- -------------------- --------------------
116        SOS_SCHEDULER_YIELD            2                    0                    0                    0
116        MEMORY_ALLOCATION_EXT          125                  0                    0                    0

运行它并再次检查等待统计数据。 我们将看到很多pagelatch_ex等待:

CREATE PROCEDURE dbo.tp_test_temp_latches
AS
BEGIN
    CREATE TABLE #t
    (
        id int IDENTITY(1,1) PRIMARY KEY,
        ss varchar(50)
    )

    INSERT INTO #t (ss)
        SELECT name FROM master.dbo.spt_values

    DELETE FROM #t
END

我用DBCC TRACEON(8666)检查了执行计划。 第一个示例显示RowSetSharing = 1。 第二个示例显示RowSetSharing = 0。

我有一些大的存储过程,在我当前的项目中使用临时表很多。我想从行集共享中受益,但我不能。我创建了Paul White博客文章,他描述了他如何通过OPTION(QUERYTRACEON 8746)关闭行集共享:changes-to-a-writable-partition-may-fail

是否可以选择打开它?还是其他任何可能性?

更新05/03/2018

我找到了一个解决方法。 为了消除过多的PAGELATCH_EX等待,我们可以使用跟踪标志8692打开“表盘”:

session_id wait_type                     waiting_tasks_count  wait_time_ms         max_wait_time_ms     signal_wait_time_ms
---------- ----------------------------- -------------------- -------------------- -------------------- --------------------
1043       PAGELATCH_EX                  2537                 5                    0                    3
1043       SOS_SCHEDULER_YIELD           2                    0                    0                    0
1043       MEMORY_ALLOCATION_EXT         132                  1                    0                    0

此选项允许读取所有需要的行,而不是更新/删除它们。所以我们将读/写操作分开。这种技术消除了PAGELATCH_EX等待,几乎两次丢弃逻辑读取。这还远不是在存储过程外使用临时表。但它比不使用此选项快两倍。

更新07/03/2018

进一步调查使我再采取一种解决方法(效率更高):

DELETE FROM #t
OPTION (QUERYTRACEON 8692)

排序运算符在内存中工作,而不是像“table spool”那样在tempdb中工作。

0 个答案:

没有答案
相关问题