The filter can be pushed down directly to the base table or index, in this case, to the clustered index scan operator.It means that the filter was pushed down to the storage engine. The storage engine tests the corresponding row in database file. If the row matches the filter, the storage engine passes it along to the query processor. If the row does not match the filter, the storage engine discards it.
代码来源于《Excessive sort memory grant》
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 ;
Why is this simple query granted so much memory? For an estimated 50 rows, the optimizer reserves almost 500 MB for the sort:
1,我在localhost 上执行,查看执行计划,Memory Grant 是 499440KB,查看Select Operator的属性 MemoryGrantInfo,其子属性是什么意思?
参考《Memory Grant Execution Plan Statistics》
“Provide memory grant estimate as well as actual runtime memory grant information. Serial required/desired memory attributes are estimated during query compile time for serial execution. The rest of attributes provide estimates and counters for query execution time considering actual degree of parallelism.”
DesiredMemory是在编译执行计划时优化器期望得到的内存
RequestedMemory 是执行计划在运行时,向SQL Server请求授予的内存
RequeiredMemory是查询语句在开始执行时必须授予的最小内存
GrantedMemory是Query Plan在执行时被授予的用于执行Sort 和 HashJoin 操作的内存
2,Paul White 的解释,赞一个
Filter 被Push-Down 到 Scan operator,使SQL Server storage engine从File读取数据时,将不满足Filter的数据行都过滤掉。
Scan Operator的Predicate是: [FilterMe]=(567),表明Filter 被push down
Sort的Input Data Path属性 Actual Number of Rows=38,表明传递到Sort Operator的数据流只有38 rows;
The filtering condition is pushed down into the scan operator as a residual predicate, but the memory granted for the sort is erroneously calculated based on the pre-filter cardinality estimate.
To illustrate the issue, we can use (undocumented and unsupported) trace flag 9130 to prevent the Filter from being pushed down into the scan operator. The memory granted to the sort is now correctly based on the estimated cardinality of the Filter output, not the scan:
SELECT T.TID, T.FilterMe, T.SortMe, T.Unused FROM dbo.Test AS T WHERE T.FilterMe = 567 ORDER BY T.SortMe OPTION (QUERYTRACEON 9130); -- Not for production systems
比较执行计划,发现多了一个Filter Operator,用于执行Query的 Where Clause, Select Operator的Memory Grant是10240KB=10M,还算合理。
参考文档: