我有一个关于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'行)。而且我想知道为什么会这样?我没得到什么?答案 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'的那些行。您可以将其视为索引搜索,然后是范围搜索。