我得出这样的结论,就像在下面的情况下确实寻找/扫描但我没有得到 为什么它在第一种情况下扫描并在第二种情况下寻找。我理解第三种情况。
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
答案 0 :(得分:4)
它在第一种情况下进行扫描的原因与第三种情况相同:索引根据字符串开头的数据进行搜索。在模式开头使用通配符时,无法智能地搜索索引以查找匹配项。索引对字符串进行了词法(字母)比较,这比比较小于/大。
树可能看起来像这样:
/nadejda
mark
/ \krishna
cab
\ /bob
anna
\allen
因此,搜索a%
可以完成,因为索引将知道每个分支的去向。例如,C> A,所以走吧。搜索%a
无法有效实现。索引必须读取所有数据,以确定每个节点是否以A结尾。必须读取所有数据意味着使用索引只是浪费了开销。
答案 1 :(得分:4)
这确实是SQL Server的工作方式。你在问为什么。
想想索引。从功能上讲,您可以将其视为按字母顺序存储contactname
- 非常类似于字典或电话簿。 (是的,它通常是一个更复杂的数据结构,通常是B树,但结果是按顺序排列的项目。)
当您说contactname like 'a%'
时,查询优化器知道它只需要查看以字母“a”开头的条目。索引确切地知道它们的位置,因此优化器可以使用搜索来获取它们。 SQL Server为like
实现了这种优化(并非所有数据库都这样做)。
当您说contactname like '%a'
时,您说“找到以'a'结尾的条目”。这很像通过字典查找以“a”结尾的所有单词。订购没有任何帮助。可能有条目以“a”开头,以“a”结尾。可能有条目以“z”开头,以“a”结尾。因此,这些类型的表达式需要扫描而不是搜索。
答案 2 :(得分:4)
好的,在你的字符串列上创建索引时,为了解决这个问题。它将以第一个字母存储它们,以便您的数据存储如下。
allen
anna
bob
cab
krishna
mark
nadejda
所以当你在做LIKE 'a%'
时,SQL服务器可以使用索引来查看结果,通过查看开头的'A'的所有内容的顺序。但是,一旦将通配符放在末尾LIKE '%A'
,您现在已经强制引擎扫描整个表以查找以字母A结尾的任何内容。
当然,这是一个非常简化的解释。