【问题标题】:Oracle performance with function in selectOracle 性能与选择功能
【发布时间】:2020-10-20 22:35:53
【问题描述】:

在我的生产环境中,当我直接在 select 中调用一个函数和当我“包装”select 然后在外面调用 then 函数时,我有一个显着的区别(下面我给你展示两个简单的例子)

在第一种情况下(直接调用函数时)结果查询在 35 秒后结束。

在第二种情况下(函数包装),结果在 7 秒内结束。

当然,查询完全一样,结果行也一样。

两种方式调用同一个函数有区别吗?

慢速版:

select col1, col2, myFun(col3)
  from aTable;

快速版本

select col1, col2, myFun(col3)
  from (select col1, col2, col3
          from aTable);

【问题讨论】:

  • 你确定这是真正的查询吗?没有WHEREJOIN 或类似的东西?
  • @Mistre83:你有没有尝试在两个语句上都写一个EXPLAIN
  • 这个功能到底是什么?执行计划是什么?函数执行了多少次?
  • 真正的查询非常“大”,我只是写了“概念”。 @SameerMirji 解释如果我在语句中有功能是有意义的?
  • @Mistre83:可能。您将通过EXPLAIN PLAN.. 找到这一点;)

标签: oracle


【解决方案1】:

假设 aTable 中有 100 万行,但您的实际查询有一个 WHERE 子句,它只返回 10 行:

select col1, col2, myFun(col3)
  from aTable
  join ...
  join ...
 where ...;

Oracle可能决定在加入和过滤之前调用函数 myFun,所以它会被调用 100 万次。由于上下文切换,从 SQL 调用 PL/SQL 函数很慢。

当你像这样包装它时:

select col1, col2, myFun(col3)
  from (select col1, col2, col3
          from aTable
          join ...
          join ...
          where ...
       );

...现在 Oracle可能会先执行连接和过滤,取回 10 行,然后调用 myFun 10 次。

如果每个函数调用需要 0.001 秒,那么第一个查询需要 1,000,000*0.001 = 1,000 秒,第二个包装查询需要 10*0.001 = 0.01 秒。

请注意,我说的是 ma​​yprobably - 优化器可以根据统计数据做出不同的选择 - 因此对于某些查询,两个版本可能只调用该函数 10 次,或者两者都调用 100 万次。

这个提示应该通过告诉 Oracle 不要将两个查询合并为一个来确保第二个版本总是很快:

select /*+ no_merge(v) */ col1, col2, myFun(col3)
  from (select col1, col2, col3
          from aTable
          join ...
          join ...
          where ...
       ) v;

【讨论】:

  • 我也猜到了这一点......也许在第一个版本中,该函数应用于每一行,而在第二个版本中,该函数应用于结果(使用 join/where)行是较少的。谢谢!
猜你喜欢
  • 2011-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 1970-01-01
  • 2012-05-15
  • 2012-11-08
  • 1970-01-01
相关资源
最近更新 更多