v_First
和
v_Second
. 当我有一个
WHERE
子句,该子句只基于其中一个视图进行筛选,但是,一旦我有了基于这两个视图的筛选条件,我就会得到两次聚集索引扫描,结果性能很差。
我的问题是:
SELECT * FROM dbo.v_First (NOEXPAND)
JOIN dbo.v_Second (NOEXPAND)
ON dbo.v_First.id = dbo.v_Second.id
WHERE
dbo.v_First.Firstname = 'JUSTIN'
OR dbo.v_Second.Surname = 'JUSTIN'
哪里
子句,然后我得到查找并执行查询,这样我就知道我已经定义了正确的索引。
(抱歉,我不能发布执行计划,它们都很简单-只需在两个视图上进行两次聚集索引扫描聚集索引和一个合并连接)
更新:
先来看看
柱:
-
ID(bigint,聚集索引)
-
名字(varchar(254),非聚集索引)
伏秒
所有索引只包含一列。
更新,第二次:
OR
子句更改为
AND
子句,则查询执行良好。我还发现,如果将查询更改为使用
UNION
或者
SELECT * FROM dbo.v_First (NOEXPAND)
JOIN dbo.v_Second (NOEXPAND)
ON dbo.v_First.ID = dbo.v_Second.ID
WHERE dbo.v_First.Firstname = 'JUSTIN'
UNION SELECT * FROM dbo.v_First (NOEXPAND)
JOIN dbo.v_Second (NOEXPAND)
ON dbo.v_First.ID = dbo.v_Second.ID
WHERE dbo.v_Second.Surname = 'JUSTIN'
据我所知,这两个查询应该是等价的?
最后,我还发现使用子查询也会产生奇怪的效果,下面的查询执行得很好:
SELECT * FROM dbo.v_First (NOEXPAND)
-- JOIN dbo.v_Second (NOEXPAND)
-- ON dbo.v_First.ID = dbo.v_Second.ID
WHERE dbo.v_First.ID IN
(
SELECT ID FROM dbo.v_Second (NOEXPAND)
WHERE dbo.v_Second.Surname = 'JUSTIN'
)
OR dbo.v_First.Firstname = 'JUSTIN'
但是如果我取消注释
JOIN
(这样我就可以从查询结果中的第二个表中获得列)然后对v峈second聚集索引进行表扫描(但是请注意,这仍然比原始查询更好,因为它只涉及1次扫描,而不是2次扫描)。
我很困惑-怎么回事?似乎我可以通过“重构”我的查询来解决这些问题,但是我担心的是我不理解这里发生了什么——我宁愿避免做出我不完全理解的更改。