为啥当我使用 column1 = 'ABCD' 过滤它时,我的一个视图的工作速度要慢 4 倍 [关闭]

Posted

技术标签:

【中文标题】为啥当我使用 column1 = \'ABCD\' 过滤它时,我的一个视图的工作速度要慢 4 倍 [关闭]【英文标题】:why one of my views works 4 times slower when I filter it with column1 = 'ABCD' [closed]为什么当我使用 column1 = 'ABCD' 过滤它时,我的一个视图的工作速度要慢 4 倍 [关闭] 【发布时间】:2012-09-13 12:31:13 【问题描述】:

我有以下脚本。为了减少执行时间,我将 get_function() 替换为常量 'ABCD' (这是 get_function() 的结果)。我希望减少执行时间;而有趣的是,执行时间增加了近 4 倍。

alter system flush buffer_cache; 
alter system flush shared_pool; 
Set timing on; 
declare x number(3); 
begin 
    select v.QTY 
    into x 
    from viewName v 
    where v.col1 = get_function() --'ABCD'; 
    exception when others then dbms_output.put_line(sqlerrm||' '||sqlcode); 
end; 
Set timing off;

【问题讨论】:

如果你能显示视图的定义会有帮助吗?请同时显示慢速和快速视图,最好也显示您的架构。如果您可以在SQLFiddle 上创建一个示例来演示这一点,那将是完美的:) 【参考方案1】:

原因是两个查询之间的执行计划发生了变化(显然前者效率更高)。

每个查询的执行计划都是独立计算的,两个语法不同的查询没有理由生成完全相同的计划。 Oracle 使用规则、统计和概括在合理的时间内生成计划。 CBO(基于成本的优化器)采取的每一步都是可能导致次优计划的近似值。通常,有了最新的统计数据,对于简单的查询,Oracle 会产生一个合理的计划。有时,您必须通过提示、精心挑选的统计数据、调整参数或其他优化工具来帮助 Oracle 选择最佳计划。

由于您没有给出其他指示,我们只能推测第二个计划更糟糕的原因。我的第一个猜测是,第二个查询产生的 INDEX RANGE SCAN 不太适合,而第一个查询产生的有效 FULL TABLE SCAN

【讨论】:

我只是将 get_function() 替换为常量“ABCD”。函数经过一些计算后返回“ABCD”。你还觉得这是索引的原因吗? 你为什么不运行一个解释计划并告诉我们? :) 您很可能会得到不同的执行计划,因为字符串 'ABCD' 是一个常量,其处理方式与可能变化的函数的结果不同(从优化器的角度来看)。可以对照列上的直方图检查常数,而函数肯定不会。这可以解释执行计划的差异。 此外,如果刷新共享池,预计第一次执行将花费更多时间(因为将从磁盘获取所有块)。尝试在不计时的情况下先运行这两个查询,然后在另一组执行中测量性能。 嗨文森特,你完全正确。原因是索引。我运行了一个解释计划并看到了巨大的差异。非常感谢您的帮助:-)【参考方案2】:

到目前为止,column1 上没有过滤器,它可能正在使用一些索引。一旦您引入了不属于任何这些索引的 column1,将执行表扫描(因为这是一个 varchar 列),因此会增加执行时间。您应该在 column1 上添加此新过滤器之前和之后查看视图的执行计划,您将能够找出正确的索引定义/修改。

【讨论】:

我刚刚将“ABCD”替换为计算并返回“ABCD”的函数。我预计我的执行时间会增加,但执行时间从 25 秒减少到 16 秒

以上是关于为啥当我使用 column1 = 'ABCD' 过滤它时,我的一个视图的工作速度要慢 4 倍 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

为啥 "abcd".StartsWith("") 返回 true?

Django:为啥当我在 django 中通过 popen 使用 Ghostscript 时会出现“找不到文件”错误

为啥“”.abcd 返回未定义的值而不是在 Javascript 中抛出未定义的错误(但 Typescript 抛出警告)

为啥我的添加好友测试路由在 insomina 中通过了 200 OK,但是当我调用获取所有用户时它没有嵌套?

使用聚合函数的问题

关于oracle instr 函数的问题 例如:instr('abcd','ab',-77,1)>0,显然没这么多位,为啥结果还会是1呢?