在最大内存设置为 25GB 的 SQL Server 2016 SP2 上,我们有一个查询在一分钟内执行大约 80 次。该查询将大约 4000 页溢出到 tempdb。这会导致 tempdb 磁盘上出现大量 IO。
当您查看查询计划(简单查询)时,您会看到估计的行数等于实际行数,但仍然会发生溢出。所以过时的统计数据不可能是问题的原因。
我做了一些测试并将查询溢出到 Tempdb:
select id --uniqueidentifier
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
但是,如果我选择不同的列,则不会发生溢出:
select startdate --datetime
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
所以我试图“扩大” id 列的大小:
select CONVERT(nvarchar(512),id)
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
然后也不会发生溢出。
为什么 uniqueidentifier 溢出到 tempdb 而不是数据时间列?当我删除大约 20000 条记录时,当我选择 id 列时也不会发生溢出。
使用以下脚本可以重现问题:
CREATE TABLE SortProblem
(
id UNIQUEIDENTIFIER,
startdate DATETIME,
sequencenumber BIGINT,
status VARCHAR(50),
PRIMARY KEY CLUSTERED(id)
)
SET nocount ON;
WITH nums(num)
AS (SELECT TOP 103000 ROW_NUMBER()
OVER (
ORDER BY 1/0)
FROM sys.all_objects o1,
sys.all_objects o2)
INSERT INTO SortProblem
SELECT newid(),
DATEADD(millisecond, num, GETDATE()),
num,
CASE
WHEN num <= 100000 THEN 'A'
WHEN num <= 101000 THEN 'B'
WHEN num <= 102000 THEN 'C'
WHEN num <= 103000 THEN 'D'
END
FROM nums
CREATE NONCLUSTERED INDEX [IX_Status]
ON [dbo].[SortProblem]([status] ASC)
INCLUDE ([sequencenumber])
启用跟踪标志 7470。
修复:当估计的行数和行大小正确时,排序运算符会溢出到 SQL Server 2012 或 SQL Server 2014 中的 tempdb
正如我在回答查询计划问题时所写: