给定 StackOverflow2010 数据库,我创建了一些外键以探索连接消除:
外键 1 - 所有评论都必须有帖子
删除未发布评论
DELETE c
FROM Comments c
LEFT JOIN Posts p
ON c.PostId = p.Id
WHERE p.Id IS NULL
创建外键
ALTER TABLE Comments
ADD CONSTRAINT fk_Comments_PostId
FOREIGN KEY (PostId) REFERENCES Posts(Id)
我们现在可以运行下面的查询并查看连接消除:
SELECT c.Id
FROM Comments c
JOIN Posts p
ON p.Id = c.PostId
计划在这里,正如我所料,只读取了评论表
外键 2 - 所有帖子必须有一个所有者用户
与上述相反,如果我重置并尝试使用以下外键,则看不到连接消除:
删除没有 OwnerUser 的帖子
DELETE p
FROM Posts p
LEFT JOIN Users u
ON p.Owneruserid = u.id
WHERE u.Id IS NULL
创建外键
ALTER TABLE Posts
ADD CONSTRAINT fk_Posts_UserId
FOREIGN KEY (OwnerUserId) REFERENCES Users(Id)
运行我的查询
SELECT p.Id
FROM Posts p
JOIN Users u
ON p.OwnerUserId = u.Id
该计划显示 SQL Server 访问两个表。
为什么外键 2 不会从连接消除中受益,而外键 1 却可以呢?
Posts上的OwnerUserId列允许为空。Comments上的PostId列不允许。
OwnerUserId中的任何空值都将导致Posts行被连接谓词消除,该谓词拒绝空值:
因此,连接会影响结果并且无法消除。
您需要明确过滤掉空值(导致Posts行集不完整)或使用外连接来查看表消除:
相关问题