为什么列上的函数会阻止使用索引?

时间:2016-06-20 16:05:45

标签: sql database indexing

在前一天我问的this question我得到了以下评论。

  

在几乎所有数据库中,列上的几乎任何函数都会阻止使用索引。这里和那里都有例外,但一般来说,函数会阻止使用索引

我用Google搜索并发现更多提及同样的行为,但我找不到比评论已经告诉我更深入的内容。

有人可以详细说明为什么会发生这种情况,也许还有避免它的策略?

4 个答案:

答案 0 :(得分:2)

索引与SQL服务器上的数据本身分开存储。因此,当您执行查询时,不应再引用应该引用以提供速度的B树索引,因为每个列上都有一个操作(函数),因此查询优化器将选择不使用索引更多。

答案 1 :(得分:2)

以下是对此原因的一个很好的解释(这是SQL Server特定的文章,但可能适用于其他SQL RDBMS系统):

https://www.mssqltips.com/sqlservertip/1236/avoid-sql-server-functions-in-the-where-clause-for-performance/

文章中真正突出的一句话是“这样做的原因是必须为每行数据评估函数值,以确定它符合您的标准。”

答案 2 :(得分:2)

让我们考虑一个极端的例子。假设您正在使用加密哈希函数查找一行,例如HASH(email_address) = 0x123456。数据库有一个基于email_address构建的索引,但现在要求它在HASH(email_address)上查找它没有的数据。 可以仍然使用索引,但最终必须查看email_address的每个索引条目并查看HASH(email_address)是否匹配。如果它必须扫描整个索引,它也可以只扫描整个表格,这样它就不必反复来回取出各个行位置。

答案 3 :(得分:2)

最基本形式的索引只是排序列数据,因此可以通过某些值轻松查找。例如,教科书可以按某种顺序排列页面,但后面的所有术语都有索引。如您所见,数据已预先计算/排序并存储在单独的区域中。

将函数应用于列并尝试根据输出匹配/过滤时,索引不再有用。让我们再看一下我们的书籍示例,并说我们应用的函数与术语相反(因此reverse('integral')变为'largetni')。您不会在索引中找到此值,因此您必须采用所有术语,将它们放入函数中,然后才进行比较。全部在查询时。最初我们可以跳过搜索i,然后搜索in,然后搜索int等等,这样就可以轻松找到该术语,因此该功能使得所有内容都变慢了。

如果您经常使用此功能进行查询,则可以提前使用reverse(term)创建索引以加快查找速度。但如果没有明确这样做,它将永远是缓慢的。