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

sql-server – 过多的排序内存授予

发布时间:2020-12-12 06:15:29 所属栏目:MsSql教程 来源:网络整理
导读:为什么这个简单的查询被授予如此多的内存? -- Demo tableCREATE TABLE dbo.Test( TID integer IDENTITY NOT NULL,FilterMe integer NOT NULL,SortMe integer NOT NULL,Unused nvarchar(max) NULL,CONSTRAINT PK_dbo_Test_TID PRIMARY KEY CLUSTERED (TID));G
为什么这个简单的查询被授予如此多的内存?
-- Demo table
CREATE TABLE dbo.Test
(
    TID integer IDENTITY NOT NULL,FilterMe integer NOT NULL,SortMe integer NOT NULL,Unused nvarchar(max) NULL,CONSTRAINT PK_dbo_Test_TID
    PRIMARY KEY CLUSTERED (TID)
);
GO
-- 100,000 example rows
INSERT dbo.Test WITH (TABLOCKX)
    (FilterMe,SortMe)
SELECT TOP (100 * 1000)
    CHECKSUM(NEWID()) % 1000,CHECKSUM(NEWID())
FROM sys.all_columns AS AC1
CROSS JOIN sys.all_columns AS AC2;
GO    
-- Query
SELECT
    T.TID,T.FilterMe,T.SortMe,T.Unused
FROM dbo.Test AS T 
WHERE 
    T.FilterMe = 567
ORDER BY 
    T.SortMe;

估计50行,优化器保留近500 MB的排序:

解决方法

这是SQL Server中的一个错误(从2008年到2014年).

我的错误报告是here.

过滤条件作为残差谓词被下推到扫描操作符中,但是基于预过滤器基数估计错误地计算为该排序授予的存储器.

为了说明问题,我们可以使用(未??记录和不支持的)跟踪标志9130来防止过滤器被压入扫描操作符.授予排序的内存现在正确地基于Filter输出的估计基数,而不是扫描:

SELECT
    T.TID,T.Unused
FROM dbo.Test AS T 
WHERE 
    T.FilterMe = 567
ORDER BY 
    T.SortMe
OPTION (QUERYTRACEON 9130); -- Not for production systems!

对于生产系统,需要采取措施以避免有问题的计划形状(将过滤器推入扫描并在另一列上进行排序).一种方法是提供过滤条件的索引和/或提供所需的排序顺序.

-- Index on the filter condition only
CREATE NONCLUSTERED INDEX IX_dbo_Test_FilterMe
ON dbo.Test (FilterMe);

使用此索引后,排序所需的内存授权仅为928KB:

更进一步,以下索引可以完全避免排序(零内存授权):

-- Provides filtering and sort order
-- nvarchar(max) column deliberately not INCLUDEd
CREATE NONCLUSTERED INDEX IX_dbo_Test_FilterMe_SortMe
ON dbo.Test (FilterMe,SortMe);

在以下SQL Server x64 Developer Edition版本上进行了测试和错误确认:

2014   : 12.00.2430 (RTM CU4)
2012   : 11.00.5556 (SP2 CU3)
2008R2 : 10.50.6000 (SP3)
2008   : 10.00.6000 (SP4)

这在SQL Server 2016 Service Pack 1修复.发行说明包括以下内容:

VSTS bug number 8024987
Table scans and index scans with push down predicate tend to overestimate memory grant for the parent operator.

经测试并确认固定于:

> Microsoft SQL Server 2016(SP1) – 13.0.4001.0(X64)开发人员版
> Microsoft SQL Server 2014(SP2-CU3)12.0.5538.0(X64)开发人员版

两种CE型号.

(编辑:李大同)

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

    推荐文章
      热点阅读