在非聚集索引中,第二列,第三列,第四列...如何排序?

时间:2017-09-13 21:20:39

标签: sql sql-server

我有一个关于SQL Server索引的问题一直困扰着我。

想象一下这样的表:

CREATE TABLE TelephoneBook (
    FirstName nvarchar(50), 
    LastName nvarchar(50), 
    PhoneNumber nvarchar(50)
)

使用这样的索引:

CREATE NONCLUSTERED INDEX IX_LastName ON TelephoneBook (
    LastName, 
    FirstName, 
    PhoneNumber
)

并想象这个表有几十万行。

我想说我想选择姓氏以B开头,名字是' John'的所有人。我会写下面的查询:

SELECT 
    * 
FROM TelephoneBook 
WHERE LastName like 'B%' 
AND FirstName='John'

由于索引可以帮助减少我们需要扫描的行数,因为它将所有以B开头的LastNames组合在一起,它是否也为FirstName执行此操作?或者数据库是否扫描以B开头的每一行,以找到名字为' John'?

换句话说,第二,第三,第四......列如何在索引中排序?在这种情况下它们也是按字母顺序排列的,所以找到约翰娜很容易吗?或者它们是某种随机或不同的顺序?

编辑:为什么我问,是因为我刚刚读过上面的SELECT语句,索引只会用于将搜索范围缩小到姓氏以B开头的记录,但索引不会用于查找其中包含Johanna的所有行(并将使用扫描所有' B'行)。而且我想知道为什么会这样?我没得到什么?

3 个答案:

答案 0 :(得分:2)

作为一种方便的简写,索引的键用于where子句直到第一个不等式。带有通配符的like被视为不平等。

因此,索引仅用于查找第一个值。但是,可能会扫描条目以匹配第一个名称,因此您仍将获得索引使用。

当然,如果优化器决定全表扫描更合适,优化器可能决定不使用索引。

答案 1 :(得分:1)

对于这个具有指定查询的实例,Gordon的回答是正确的。一般来说,你应该意识到它并没有把记录分组在一起,而是在#34;桶和#34;基于列的值,而是根据索引的键列对它们进行排序。换句话说,您在此索引中的记录将根据LastName进行排序,对于共享相同LastName值的记录,它们将按FirstName值进一步排序,然后按PhoneNumber值排序。您没有为此索引上的列指定排序顺序,但是SQL Server defaults unspecified sort orders to ASC(ending),因此这些列确实在索引中进行词法排序。

在您的特定情况下,查询优化器已决定查看第一列的索引以确定要抓取哪些记录,正如Gordon的回答提到的那样,但是如果优化器决定这样做,SQL Server将重新排序谓词更好,可能会使用更多的索引列或根本不使用索引列,具体取决于查询本身和您要查询的记录的统计信息。

答案 2 :(得分:0)

从逻辑上讲,索引按键的顺序按键值排序。所以在这种情况下,LastName(按文本排序),FirstName(作为文本),然后是PhoneNumber(按文本排序)...任何包含的列都不会被排序。

在你的情况下,我们知道尾随通配符仍然是SARGable,所以我们期望看到一个索引寻求将数据缩小到所有数据w / LastNames以“B”开头,从该数据池开始,它将进一步过滤以仅包含具有FirstName ='John'的那些行。您可以将其视为索引搜索,然后是范围搜索。