gpt4 book ai didi

sql - 为什么 SQL Server 不使用我的索引? (过滤连接的索引 View )

转载 作者:行者123 更新时间:2023-12-03 03:31:43 25 4
gpt4 key购买 nike

我有两个索引 View ,v_Firstv_Second。当我有一个仅基于这些 View 之一进行过滤的 WHERE 子句时,这些 View 效果很好,但是一旦我有了基于这两个 View 的过滤条件,我就会得到两次聚集索引扫描,并且性能较差结果。

我的查询是:

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'

如果我注释掉上述两个 WHERE 子句中的任何一个,我就会进行查找并执行查询,这样我就知道我单独定义了正确的索引。

为什么在基于多个索引 View 进行过滤时查询不执行,我该如何解决这个问题?

(抱歉,我无法发布执行计划,它们无论如何都是微不足道的 - 只需对两个各自的 View 聚集索引和合并联接进行两次聚集索引扫描)

更新:

v_First 列:

  • ID(bigint,聚集索引)
  • 名字(varchar(254),非聚集索引)

v_Second 列:

  • ID(bigint,聚集索引)
  • 姓氏(varchar(254),非聚集索引)

所有索引仅包含单个列。

更新,第二个:

我发现,如果将 OR 子句更改为 AND 子句,则查询执行得很好。我还发现,如果我将查询更改为使用 UNION 语句而不是 OR ,查询将执行良好:

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 次)。

我很困惑 - 发生了什么事?看来我可以通过“重构”我的查询来解决这些问题,但是我担心我不明白这里发生了什么 - 我宁愿避免进行我不完全理解的更改。

最佳答案

观察结果

  • 您有一个不可SARGable 的“OR”条件

  • 您可能需要向每个索引添加 ID,以便无需扫描/查找即可使用

  • 无论如何,我想看看这些计划。使用SET SHOWPLAN_TEXT

为了回答你的问题,我可能会在基表上有一个包含两个文本列的索引,并让它扫描该索引。 OR 并没有给你很多选择,恕我直言,2 个索引 View 是毫无意义的。更新后,您有一些人为的 SQL 构造:您真的需要 2 个索引 View 和一个奇特的派生表或 UNION 吗?

关于sql - 为什么 SQL Server 不使用我的索引? (过滤连接的索引 View ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3445448/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com