当 WHERE 子句中只有一列时,SQL Server 会使用复合索引吗?

Posted

技术标签:

【中文标题】当 WHERE 子句中只有一列时,SQL Server 会使用复合索引吗?【英文标题】:Will SQL Server use a compound index when only a single column is in the WHERE clause? 【发布时间】:2011-01-14 18:03:07 【问题描述】:

假设我有一张桌子:

CREATE TABLE Users (
    Id INT IDENTITY (1, 1),
    FirstName VARCHAR(40),
    LastName VARCHAR(40)
)

查询通常针对 FirstNameLastName,但也针对 FirstName LastName em>。

如果我在 FirstName 上创建一个非聚集索引,在 LastName 上创建另一个索引,那么我的前两个查询将得到满足。显然,SQL Server 将使用index intersection 进行其他查询。

或者,如果我在 (FirstName) 和 (LastName, FirstName) 上有索引,SQL Server 是否可以/是否将第二个索引用于仅对 LastName 的查询以及对两者的查询?

SQL Server 是从左到右还是从右到左存储复合索引部分?换句话说:它会将密钥构建为 LastNameFirstName 还是 FirstNameLastName?还是可以随意选择一个?

【问题讨论】:

【参考方案1】:

SQL Server 可以/是否使用索引 (LastName, FirstName) 来查询 LastName 以及同时查询这两者?

是的,数据库将使用索引 (LastName, FirstName) 来查询 LastName。不过,它不会将此索引用于仅对 FirstName 的查询。

它是从左到右还是从右到左存储复合索引部分?

存储在B-Tree 中。无论您认为它是从右到左还是从左到右存储,都只是一种有用的可视化辅助工具,与实际的数据存储无关。

【讨论】:

我的意思是:在构建放入 B-Tree 的键时,是存储为 (A,B,C) 或 (C) 的复合索引 (A,B,C) 的键, B,A),还是由 SQL Server 任意选择一个? 我认为他的意思是密钥是如何构造的。答案是从左到右,与您定义的键完全一样。这就是为什么它不能用于搜索姓氏。【参考方案2】:

是的,如果您仅查询姓氏,它应该使用 (LastName, FirstName) 索引。因此,它既可以单独使用 LastName 查询,也可以同时使用 LastName 和 FirstName。

一般准则是确保具有最大选择性的列首先出现在复合索引中,因为这会在随后的选择性较低的列之前提供最大的好处/缩小结果集。

【讨论】:

【参考方案3】:

根据您发送的实际查询,即使您只搜索第二列,也可以使用两列的复合索引。但是,您不会进行索引搜索,但很可能会进行索引扫描。如果这对您来说“足够好”,则取决于您的特定环境。索引与其说是一门科学,不如说是一门艺术,许多不同的因素会影响您对如何索引表的决定。这始终是一种权衡,因为表上的索引过多与索引过少一样糟糕。确保您最重要的查询得到很好的覆盖,然后根据具体情况决定是否有任何额外的索引值得其花费。

另外,由于它尚未被提及,但前提是您至少在 SQL Server 2005 上:让我为非聚集索引添加 INCLUDE 子句。这是一个被忽视但对任何索引策略都非常有用的补充。

【讨论】:

以上是关于当 WHERE 子句中只有一列时,SQL Server 会使用复合索引吗?的主要内容,如果未能解决你的问题,请参考以下文章

ORA-01722: 无效的数字 where 子句

SQL LEFT JOIN 与另一列的 where 子句

当用户在 MS Access 中修改表中的另一列时,如何在 SQL Server 中将列设置为今天的日期 [关闭]

where子句中的SSRS参数用法

更新另一列时自动更新sql列

Spring JPA:从没有where子句的表中查询一列