sql - SUM 比循环慢

标签 sql oracle plsql

我目前正在尝试优化一个不是我写的 View 。它真的很复杂,有很多 View 使用使用 View 的函数等等。
所以,玩我可以优化的东西,我有一些我无法真正理解的东西:
我有这个功能:

create or replace FUNCTION at_get_tourenrechnungssumme_br (in_rechnr IN rechnungen.rechnr%TYPE)
      RETURN NUMBER
   IS
      CURSOR c1 (
         int_rechnr   IN rechnungen.rechnr%TYPE)
      IS
         SELECT (ROUND (
                     verrechnung.get_betrag (bt.buchid, bt.betrag_euro)*(1+b.mwst/100),
                   2))
                   betrag
           FROM buchungen_touren bt, v_buchkz b
          WHERE     bt.rechnr = int_rechnr
                AND bt.storniert_jn = 0
                AND bt.buchid = b.ID;
      int_return   NUMBER (11, 2) := 0;
   BEGIN
      FOR c1_rec IN c1 (in_rechnr)
      LOOP
         int_return := (int_return + c1_rec.betrag);
      END LOOP;

      RETURN NVL (int_return, 0);
   END at_get_tourenrechnungssumme_br;

我只是想:循环不好,你可以用 sum 做同样的事情:
create or replace FUNCTION at_get_tourenrechnungssumme_br (in_rechnr IN rechnungen.rechnr%TYPE)
      RETURN NUMBER
   IS
      int_return   NUMBER (11, 2) := 0;
   BEGIN
      SELECT sum(ROUND (
                     verrechnung.get_betrag (bt.buchid, bt.betrag_euro)*(1+b.mwst/100),
                   2))
                   betrag
           into int_return        
           FROM buchungen_touren bt, v_buchkz b
          WHERE     bt.rechnr = in_rechnr
                AND bt.storniert_jn = 0
                AND bt.buchid = b.ID;

      RETURN NVL (int_return, 0);
   END at_get_tourenrechnungssumme_br;

奇怪的是,它实际上慢了大约 2 倍。是否sum只是不喜欢函数?
有人可以解释一下吗?

编辑:
这更像是一个理论问题。显而易见的解决方案是:避免使用函数(我经常这样做,当我优化 View 时,别人写的),我做了,但我认为,这个问题仍然很有趣。

最佳答案

运行时间的差异归结为 PL/SQL/SQL 上下文切换。将 PL/SQL 函数嵌入 SQL 语句时,Oracle 需要在两个引擎之间来回切换。考虑这个非常简单的测试,但它说明了差异。

创建一个简单的函数

SQL> CREATE OR REPLACE FUNCTION test (a IN number, b in NUMBER) RETURN NUMBER
  2  AS
  3  
  4  BEGIN
  5          return a+b;
  6  END;
  7  /

Function created.

在纯 SQL 中执行加法和聚合的简单查询
  1  WITH
  2  row_gen
  3  AS (
  4 SELECT LEVEL as a, level as b
  5 FROM DUAL
  6 CONNECT BY LEVEL < 1000000
  7 )
  8  SELECT SUM(a+b)
  9* FROM row_gen
SQL> /

  SUM(A+B)
----------
1.0000E+12

Elapsed: 00:00:00.36

使用 PL/SQL 函数调用执行聚合的简单查询
  1  WITH
  2  row_gen
  3  AS (
  4 SELECT LEVEL as a, level as b
  5 FROM DUAL
  6 CONNECT BY LEVEL < 1000000
  7 )
  8  SELECT SUM(test(b,b))
  9* FROM row_gen
SQL> /

SUM(TEST(B,B))
--------------
    1.0000E+12

Elapsed: 00:00:00.87

因此,纯 SQL 示例需要 0.36 秒,而使用 SQL/PLSQL 上下文切换的示例所需时间是 0.87 秒的两倍多。

关于sql - SUM 比循环慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27546572/

相关文章:

sql - SQL 中的替换和分组依据

sql - 操作数数据类型 float 对 '^' 运算符无效

Oracle 错误 ORA-06512

mysql - 获取所选年份的所有日期

mysql - 替换 MySQL 中的所有字段

database - Oracle 中的约束/外键信息

Oracle View 不可更新,关于 Instead Of 触发器的建议

sql - 有效日期格式检查 Oracle - 奇怪的行为

oracle - PL/SQL Append_Values 提示给出错误消息

sql - Oracle SQLPlus : Echo without line numbers?