具有基于函数的索引的虚拟列的预期用例是什么?
我问的原因(新手):
我一直在探索用于预先计算表中列的选项。例如,在道路表中,使用区域表中的空间相交区域编号填充字段。更多信息在这里:计算字段的选项。
我的经验是空间查询通常很慢——无论是使用 Oracle 的 SDO_GEOMETRY 数据类型/函数还是使用用户定义的对象类型,如 Esri 的 ST_GEOMETRY 数据类型/函数。因此,我确实希望预先计算该计算——以避免每次使用查询时不断进行昂贵的计算。
起初,我很想用基于函数的索引创建一个虚拟列。但是现在(根据其他人的意见),我开始怀疑使用基于函数的索引预计算列可能不适合 FBI。相反,我想知道使用触发器简单地计算表中的字段是否是更好的选择。(我知道物化视图也是一种选择。但我没有 CREATE MATERIALIZED VIEW 权限。)
所以,长话短说,我怀疑虚拟专栏和 FBI 不适合我的用例。话虽如此,虚拟专栏和 FBI 的正确用例是什么?
虚拟列不会自行预先计算任何内容,您只是将表达式存储在元数据中。如果您计划对这些表达式进行过滤,那么您可能出于以下几个原因需要一个虚拟列 - 您不需要每次都编写整个表达式,Oracle 将为您收集针对该列的统计信息,以便您获得更好的计划 (如果您的查询足够复杂以至于这个基数很重要)。
虚拟列上的(基于函数的)索引可以更快地过滤表达式,因为表达式现在已被索引,因此您可以快速查找(它是一个索引)。您也不必创建虚拟列 - 您可以针对表达式创建基于函数的索引,但这意味着您每次都必须再次输入整个表达式(尽管 Oracle 对您输入的方式非常宽容)。您仍然可以获得统计信息的好处,因为索引将具有统计信息,并且在后台将有一个不可见的列可以对其进行统计(尽管我相信默认情况下不会发生这种情况)。
如果您这样做,请注意您的表达式是确定性的,结果应该只根据行而变化。这还包括诸如 NLS 参数之类的东西,它们可能会给您带来不同的结果。几个版本之前有一个错误修复,其中 Oracle 禁用了正则表达式的索引,因为它们可能依赖于语言设置,如果你强制这样做,那么你最终可能会得到损坏的数据。
触发器可以工作,但我已经数不清有多少次我看到在触发器中做出的假设最终导致损坏。物化视图可以让您对更复杂的表达式进行索引,但您必须重新存储整个结果集和附加索引。您还需要确保可以适当地刷新物化视图,随着复杂性的增加,快速刷新变得更加困难。