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

问题描述:

我有关于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的行数,它也为做到这一点名字?或者数据库扫描以B开头的每一行以找到名为'John'的那一行?

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

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

作为一种便利的速记,索引的关键字用于where子句,直至第一个不等式。带有通配符的like被认为是不等式。

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

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

+0

对小表进行全表扫描的成本要低于在同一个表上对非聚集索引的查找。我已经看到人们强制索引使用25个行表,因为全表扫描是不好的。很酷的答案 – Namphibian

戈登的答案在这个例子中是正确的,并带有指定的查询。一般而言,您应该意识到,它并不是根据列的值将“记录”中的记录组合在一起,而是根据索引的关键列对其进行排序。换句话说,您在此索引中的记录将按照LastName排序,对于共享相同LastName值的记录,它们将按FirstName值进一步排序,然后按PhoneNumber值进行排序。您没有为此索引中的列指定排序顺序,但是SQL Server defaults unspecified sort orders to ASC(ending),因此这些列在索引中确实按词汇顺序排序。正如Gordon的回答所提到的那样,查询优化器决定查看第一列的索引以确定要抓取哪些记录,但是如果优化器决定更好,SQL Server将重新排列谓词,根据查询本身和您正在查询的记录的统计信息,可能会使用索引的更多列或根本没有。

从逻辑上讲,索引按键值顺序排列。因此,在这种情况下,LastName(按文本排序),FirstName(以文本形式排列),然后是PhoneNumber(按文本排序)...任何包含的列根本不排序。

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