为什么没有分区消除

Tho*_*anz 6 sql-server partitioning sql-server-2014

我有一个包含 3 行的临时表 #termin

当我执行以下查询时

SELECT t.termin, ttw.tourid, twt.va_nummer_int
  FROM #term AS t
 INNER JOIN plinfo.t_touren_werbeflaechentermine AS ttw
     ON ttw.termin = t.termin
  INNER JOIN wtv.t_werbeflaechentermine AS twt 
     ON twt.jahr   = t.jahr
    AND twt.termin = t.termin
    AND twt.ID_Wt  = ttw.id_wt
    GROUP BY t.termin, ttw.tourid, twt.va_nummer_int
Run Code Online (Sandbox Code Playgroud)

我会得到以下执行计划: 在此处输入图片说明

每个表都使用匹配的索引进行连接。两个表都由 ps_termin(termin) 进行分区。

对于第一个表 (t_touren_werbeflaechentermine),它执行分区消除并仅读取行的一个子集,而对于第二个表 (t_werbeflaechentermine),它扫描整个索引 ( jahr, termin, id_wt include (va_nummer_int))。

所以我的问题是:为什么它是索引扫描(而不是搜索),为什么它不消除第二个表的分区。

PS:在WITH (FORCESEEK)第二个表上使用时,它会在执行计划中切换两个表并对第一个表进行全索引扫描......

PPS:可以在此处找到执行计划

Geo*_*son 9

为什么要进行索引扫描?

与循环查找方法相比,SQL Server 估计扫描数据的成本可能更低(只有 1.7 MM 行,因此是一个相对较小的表)。

扫描t_werbeflaechentermine表将处理所有1,708,658行,您的计划表明这将执行7,347 logical reads.

估计执行循环搜索~70K seeks(循环外侧的基数估计)。如果我们假设一个搜索是一个二分搜索,我们可能因此估计这将具有70109.4 * LOG(1708658,2), 或的复杂度1,451,575

这略低于1,708,658扫描处理的行数,但逻辑读取的数量会高得多,因为每个(估计的)~70K 搜索将执行几次逻辑读取,产生比选择的扫描更多的逻辑读取。这可能是循环搜索计划产生更高的估计成本而未被选中的原因。

无需扫描即可查看计划

如果您想将此计划与对两个连接都使用循环搜索的执行计划进行比较,您可以尝试将OPTION (LOOP JOIN)查询提示添加到您的查询中,以便两个连接都使用循环连接。发布此实际执行计划以进行比较将很有帮助。

为什么没有分区消除?

我相信不会发生分区消除,t_werbeflaechentermine因为 SQL Server 没有散列连接算法,该算法根据散列连接的构建端观察到的分区执行分区消除。在某些情况下,这将是一个很好的优化,但据我所知,在当前优化器中不可用:分区消除可用于循环连接的内侧,但不适用于散列连接的探测端(除非查询包含分区列上的显式谓词)。

为了进一步阅读,SQL Server 确实有并置连接的概念,其中散列连接独立应用于两个以相同方式分区的表的每个分区。但是,此优化仅适用于 2 路连接,因此您的查询不符合条件。Paul White 在提高分区表连接性能中更详细地描述了这个和其他分区表连接注意事项。