【问题标题】:Why do functions on columns prevent the use of indexes?为什么列上的函数会阻止使用索引?
【发布时间】:2016-10-21 23:27:40
【问题描述】:

在前几天我问过的this question 上,我收到了以下评论。

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

我四处搜索,发现更多关于相同行为的提及,但我很难找到比评论已经告诉我的更深入的内容。

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

【问题讨论】:

  • Oracle 中至少有功能索引。这可能是这里和那里的例外之一:-)

标签: sql database indexing


【解决方案1】:

最基本形式的索引只是排好序的列数据,因此很容易通过某个值进行查找。例如,一本教科书可以按某种顺序排列页面,然后在后面为所有术语提供索引。如您所见,数据已预先计算/排序并存储在单独的区域中。

当您将函数应用于列并尝试根据输出进行匹配/过滤时,索引不再有用。让我们再看一下我们的书示例,并说我们正在应用的函数是术语的反面(所以reverse('integral') 变成了'largetni')。您不会在索引中找到此值,因此您必须获取所有术语,将它们放入函数中,然后再进行比较。全部在查询时。最初我们可以跳过搜索i,然后是in,然后是int等等,这样可以很容易地找到这个词,所以这个函数让一切都变慢了。

如果您经常使用此功能查询,您可以提前使用reverse(term) 建立索引以加快查找速度。但是如果不明确这样做,它总是会很慢。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      这里很好地解释了为什么会发生这种情况(这是一篇 SQL Server 特定文章,但可能适用于其他 SQL RDBMS 系统):

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2018-10-07
          • 1970-01-01
          • 2020-02-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-15
          • 2021-08-12
          相关资源
          最近更新 更多