以下是查询存储遇到的性能问题的简化:
CREATE TABLE #tears
(
plan_id bigint NOT NULL
);
INSERT #tears (plan_id)
VALUES (1);
SELECT
T.plan_id
FROM #tears AS T
LEFT JOIN sys.query_store_plan AS QSP
ON QSP.plan_id = T.plan_id;
该plan_id
列被记录为 的主键sys.query_store_plan
,但执行计划没有像预期的那样使用连接消除:
- DMV 没有投影任何属性。
- DMV 主键
plan_id
不能复制临时表中的行 - 使用了 A ,因此无法删除
LEFT JOIN
任何行。T
这是为什么,如何才能在此处获得连接消除?
该文档有点误导。DMV 是非物化视图,因此没有主键。底层定义有点复杂,但简化的定义
sys.query_store_plan
是:此外,
sys.plan_persist_plan_merged
也是一个视图,尽管需要通过专用管理员连接进行连接才能查看其定义。再次,简化:上的索引
sys.plan_persist_plan
是:So
plan_id
被限制在 上是唯一的sys.plan_persist_plan
。现在,
sys.plan_persist_plan_in_memory
是一个流式表值函数,呈现仅保存在内部存储器结构中的数据的表格视图。因此,它没有任何独特的约束。因此,本质上,正在执行的查询等同于:
...不会产生连接消除:
切入问题的核心,问题是内部查询:
...很明显,左连接可能会导致行
@t2
被复制,因为@t3
对 没有唯一性约束plan_id
。因此,无法消除连接:为了解决这个问题,我们可以明确地告诉优化器我们不需要任何重复
plan_id
值:@t3
现在可以消除外部连接:将其应用于实际查询:
同样,我们可以添加
GROUP BY T.plan_id
而不是DISTINCT
.plan_id
无论如何,优化器现在可以通过嵌套视图一直正确地推断属性,并根据需要消除两个外部连接:请注意,使
plan_id
临时表中的唯一性不足以获得连接消除,因为它不会排除不正确的结果。我们必须明确拒绝plan_id
最终结果中的重复值,以允许优化器在这里发挥其魔力。