Sql 为什么当我使用column1='过滤某个视图时,它的运行速度慢了4倍;ABCD';

Sql 为什么当我使用column1='过滤某个视图时,它的运行速度慢了4倍;ABCD';,sql,oracle,view,plsql,toad,Sql,Oracle,View,Plsql,Toad,我有以下脚本。为了减少执行时间,我将get_函数()替换为常量“ABCD”(这是get_函数()的结果)。我希望减少执行时间;然而,有趣的是,执行时间几乎增加了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

我有以下脚本。为了减少执行时间,我将get_函数()替换为常量“ABCD”(这是get_函数()的结果)。我希望减少执行时间;然而,有趣的是,执行时间几乎增加了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;

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

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


既然你没有给出其他指示,我们只能推测第二个计划更糟糕的原因。我的第一个猜测是,第二个查询生成的
索引范围扫描
不太合适,而第一个查询生成的是高效的
全表扫描

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

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


既然你没有给出其他指示,我们只能推测第二个计划更糟糕的原因。我的第一个猜测是,第二个查询生成的
索引范围扫描
不太合适,而第一个查询生成的是高效的
全表扫描

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

到目前为止,如果没有第1列上的筛选器,它可能使用了一些索引。一旦引入了column1(它不是这些索引的一部分),就会执行表扫描(因为这是一个varchar列),从而增加了执行时间。在第1列添加此新筛选器之前和之后,您应该仔细查看视图的执行计划,这样您就能够找到正确的索引定义/修改。

如果您可以显示视图的定义,会有帮助吗?请同时显示慢速和快速视图,最好也显示您的模式。如果您可以创建一个示例来演示这一点,那将是完美的:)如果您可以显示视图的定义,这会有帮助吗?请同时显示慢速和快速视图,最好也显示您的模式。如果您可以创建一个示例来演示这一点,那将是完美的:)我刚刚用一个计算并返回“ABCD”的函数替换了“ABCD”。我希望我的执行时间增加,但执行时间从25秒减少到了16秒。我只是用一个计算并返回“ABCD”的函数替换了“ABCD”。我希望我的执行时间会增加,但执行时间从25秒减少到了16秒。我只是将get_函数()替换为常量“ABCD”。函数在进行一些计算后返回“ABCD”。你还认为这是因为索引吗?为什么不运行一个解释计划并告诉我们呢?:)您很可能会得到不同的执行计划,因为字符串“ABCD”是一个常量,它的处理方式与函数的结果不同(从优化器的角度来看)。可以根据列上的直方图检查常量,而函数肯定不会。这可以解释执行计划的不同。而且,如果刷新共享池,第一次执行将花费更多的时间(因为所有块都将从磁盘获取)。尝试先不计时地运行两个查询,然后在另一组执行中测量性能。嗨,Vincent,你完全正确。原因是索引。我运行了一个解释计划,看到了巨大的差异。非常感谢您的帮助:-)我只是将get_函数()替换为常量“ABCD”。函数在进行一些计算后返回“ABCD”。你还认为这是因为索引吗?为什么不运行一个解释计划并告诉我们呢?:)您很可能会得到不同的执行计划,因为字符串“ABCD”是一个常量,它的处理方式与函数的结果不同(从优化器的角度来看)。可以根据列上的直方图检查常量,而函数肯定不会。这可以解释执行计划的不同。而且,如果刷新共享池,第一次执行将花费更多的时间(因为所有块都将从磁盘获取)。尝试先不计时地运行两个查询,然后在另一组执行中测量性能。嗨,Vincent,你完全正确。原因是索引。我运行了一个解释计划,看到了巨大的差异。非常感谢您的帮助:-)