5

我得出了这样的结论,就像在下面的情况下确实搜索/扫描但我没有得到为什么它在第一种情况下扫描和在第二种情况下搜索。我理解了第三种情况。

SELECT c.contactname FROM Sales.Customers c
WHERE c.contactname LIKE '%a'-- Does a Scan 1st Case

SELECT c.contactname FROM Sales.Customers c
WHERE c.contactname LIKE 'a%'-- Does a Seek 2nd Case

SELECT c.contactname FROM Sales.Customers c
WHERE c.contactname LIKE '%a%'-- Does a Scan

如果我在contactname 上建立一个索引,该索引具有以下示例数据,那么索引树将如何......就像我们为数字构建它一样,它将比较小于大于并且将遍历索引树在以下情况下的遍历方式。

c.contactname

mark
anna
krishna
nadejda
allen
bob
cab
4

3 回答 3

4

它在第一种情况下进行扫描,原因与第三种情况相同:索引根据字符串开头的数据进行搜索。在模式开头使用通配符,无法智能地搜索索引以查找匹配项。该索引对字符串进行字典(字母)比较,这是一个小于/大于比较。

树可能看起来像这样:

        /nadejda
    mark
   /    \krishna
cab
   \    /bob
    anna
        \allen

因此,可以进行搜索a%,因为索引会知道每个分支的去向。例如,C > A,所以向左走。搜索%a效率不高。索引必须读取所有数据以确定每个节点是否以 A 结尾。必须读取所有数据意味着使用索引只是浪费开销。

于 2013-04-18T13:41:10.323 回答
4

这确实是 SQL Server 的工作方式。你在问为什么。

想想指数。从功能上讲,您可以将其视为contactname按字母顺序存储 - 很像字典或电话簿。(是的,它通常是一个更复杂的数据结构,通常是 B 树,但结果是按顺序排列的项目)。

当您说contactname like 'a%'时,查询优化器知道它只需要查看以字母“a”开头的条目。索引确切地知道它们在哪里,因此优化器可以使用搜索来找到它们。SQL Server 实现了这种优化like(并非所有数据库都这样做)。

当您说 时contactname like '%a',您是在说“找到以 'a' 结尾的条目”。这很像通过字典查找所有以“a”结尾的单词。订购没有任何帮助。可能存在以“a”开头并以“a”结尾的条目。可能存在以“z”开头并以“a”结尾的条目。因此,这些类型的表达式需要扫描而不是查找。

于 2013-04-18T13:44:23.507 回答
4

好的,当您在字符串列上创建索引时,为您分解这一点。它将按第一个字母存储它们,因此您的数据将像这样存储。

allen
anna
bob
cab
krishna
mark
nadejda

因此,当您在执行操作时,您的LIKE 'a%'Sql 服务器可以通过查看开头带有“A”的所有内容的顺序来使用索引来减少结果。但是,一旦您将通配符放在末尾LIKE '%A',您现在就强制引擎扫描整个表以查找以字母 A 结尾的任何内容。

当然,这是一个非常简单的解释。

于 2013-04-18T13:48:22.780 回答