使用 BETWEEN join -eager spool 解决性能问题

Met*_*hor 2 performance sql-server sql-server-2014 query-performance

执行此查询(匿名)大约需要 2 分钟。

SELECT  
    ly.Col1 
    ,sr.Col2
    ,sr.Col3
    ,sr.Col4
INTO TempDb..TempLYT
FROM Tempdb..T1 ly
JOIN TempDb..T2 sr on sr.[DateTimeCol] BETWEEN ly.DateTimeStart and ly.DateTimeEnd
WHERE sr.Col5 = 1 OR sr.Col5 = 2
Run Code Online (Sandbox Code Playgroud)

查询计划

是否有一些替代方案可以帮助解决此查询?

应用 Paul White 建议的索引后,查询计划如下所示:

优化的查询计划

Pau*_*ite 8

确保您在 T1 上有一个索引,例如:

CREATE INDEX i ON T1 (dtstart, dtend) INCLUDE (col1);
Run Code Online (Sandbox Code Playgroud)

您可以根据哪个对您的数据集更具选择性来反转关键列。

优化器倾向于为其中一个不等式引入一个急切的假脱机,并将第二个留在过滤器中。复述:

CREATE TABLE #T1 (col1 integer, dtstart datetime, dtend datetime);
CREATE TABLE #T2 (col2 integer, col3 integer, col4 integer, col5 integer, dtcol datetime);

UPDATE STATISTICS #T1 WITH ROWCOUNT = 5000;
UPDATE STATISTICS #T2 WITH ROWCOUNT = 100000;

SELECT
    T1.col1,
    T2.col2,
    T2.col3,
    T2.col4
FROM #T1 AS T1
JOIN #T2 AS T2 ON T2.dtcol BETWEEN T1.dtstart AND T1.dtend
WHERE T2.col5 IN (1, 2)
OPTION (QUERYTRACEON 8690); -- No perf spool
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

随着索引:

在此处输入图片说明

自然,搜索仅针对第一个索引列。第二个将是残差谓词。

通常,间隔查询很难优化。Dejan Sarka 和 Itzik Ben-Gan 对这个话题有一些很好的报道: