我目前正在尝试优化视图,这不是我写的.它非常复杂,使用了使用视图等功能的很多视图.所以,玩弄我可以优化的东西我有一些我无法理解的东西:我有这个功能:
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;
Run Code Online (Sandbox Code Playgroud)
我只是想:循环是坏的,你可以用总和做同样的事情:
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;
Run Code Online (Sandbox Code Playgroud)
奇怪的是,它实际上很慢,因为〜2.难道sum只是不喜欢的功能呢?有人可以解释一下吗?
编辑:这更像是一个理论问题.显而易见的解决方案是:避免使用函数(我主要做的是,当我优化视图,其他人写的时候),我做了,但我认为,问题仍然很有趣.
小智 1
运行时间的差异在于 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.
Run Code Online (Sandbox Code Playgroud)
在纯 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
Run Code Online (Sandbox Code Playgroud)
使用 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
Run Code Online (Sandbox Code Playgroud)
因此,纯 SQL 示例需要 0.36 秒,而带有 SQL/PLSQL 上下文切换的示例则需要略多一倍的时间,为 0.87 秒。