我可以通过在其他索引中包含列来“链接”SQL Server中的非聚集索引吗?

问题描述:

我有一个表,my_table,列a,b,c, d,e我可以通过在其他索引中包含列来“链接”SQL Server中的非聚集索引吗?

我有一个查询过滤器上ab,并c并返回de;我有另一个查询过滤bc,并返回de。如果我创建了以下指标:

CREATE NONCLUSTERED INDEX 
    ON my_table (a) 
    INCLUDE (b); 

CREATE NONCLUSTERED INDEX 
    ON my_table (b,c) 
    INCLUDE (d,e); 

第一个查询(过滤上abc)可以同时使用索引?

SQL Server 2008 R2,如果它很重要。

+0

我不这么认为(并且我怀疑它会有效),SQL查询分析器说什么?是否包含(b,c)不是一个选项? – eckes

是的,它叫做索引相交,https://www.brentozar.com/archive/2016/06/lets-make-match-index-intersection/

然而,为了实现这一点,SQL Server必须确定每个索引查找都会削减表中匹配行的总数,但仍会导致返回多个行,但是两次查找的交集又显着减少表中匹配行的数量,而不是仅针对一个查找。

因为我假设你真正的问题是如果你应该创建一个合理的性能来处理这个查询的第三个索引,我的一般答案是否定的,你不应该。索引交集很可能是SQL Server在最坏情况下使用的一种可能性,即只针对一个索引进行查找时,不会显着过滤足够多的行以证明书签查找的正确性。

有一种情况,第三个索引可能是有益的,当且仅当针对两个当前索引的查找结果返回大部分表行时,但两个结果的交集非常小。对于SQL Server来说,从两个分支中抽取多行并将行与行匹配可能比单个索引重一次以返回非常少的行要重得多。只有你能够很好地了解你的数据,但看起来不太可能,并且很可能意味着你现有的两个索引当前没有足够的选择性,不足以用于索引查找。

通常没有。

我听说在极少数情况下,SQL Server的后续版本可以对一个操作使用多个索引,但是告诉我这个的人说他从未见过它实际发生过。

想想这样,你会如何在C#中编写代码?

只使用第一个索引,您会找到您的行,然后在聚簇索引中为缺失的数据执行散列表查找。

使用这两个索引,您会在第一个索引中找到您的行,然后使用嵌套循环执行完整索引扫描。也就是说,对于来自索引的每个匹配记录(out循环),您将遍历第二个索引中的每个记录以查找匹配(内部/嵌套循环)。

或者使用这两个索引,你会发现第一个索引中的所有行和第二个索引中的所有行。然后,你将不得不弄清楚如何根据主键加入两个列表,可能使用嵌套循环。

仅仅给出两个查询和它们查看的列,很难说出它将使用哪些索引。索引使用完全基于统计数据,并且执行计划是围绕这个建立的。即使你有一个索引,在一张足够小的表上,你将得到索引扫描而不是寻找,因为它不会节省时间或读取来完成扫描。

要知道它将使用哪些指标,您需要知道a)表格有多大b)a,b,c单独有多少c)基于b)的估计/实际执行计划。这决定了你的索引使用。服务器将使用任何它认为会以最快的速度获得结果的计划。

对于服务器生成执行计划乔纳森上述发生,它会采取一个相当具体的数据集。独特的(或实际上唯一的)a,b,c使索引值得使用,一个深度和宽度很大的表,这将阻碍关键查找。当然,统计数据需要真实地表示执行计划考虑使用两个索引。