kor*_*efn 1 plsql clojure query-optimization
我有一个大表,希望迭代记录(> 1,000,000),根据另外2组每个表> = 1执行一些检查,并将结果输出到文本文件.
执行此操作的PL\SQL需要几个小时,我可以对其进行优化,或者我可以将其重写为可并行化的clojure程序,因为只有选择而且没有写入(对表).
问题:1优化PL/SQL有哪些挑战/限制?
2在优化PL/SQL方面,将代码迁移到clojure是否有重大的优势?
编辑 这是它的肉
OPEN cur;
LOOP
FETCH cur INTO l_cur;
EXIT WHEN cur%NOTFOUND;
SELECT NVL (dUM ( (total - total_old)), 0),
NVL (dUM ( (new - old)), 0)
INTO li_debt, li_debt
FROM tbl1
WHERE accounting_date = l_cur.accounting_date
AND USER_ID = l_cur.USER_ID
AND USER_ACCOUNT = l_cur.USER_ACCOUNT;
SELECT NVL (
dUM (
DECODE (a.DEBITS,
'foo', ABS (amount),
ABS (amount) * -1)),
0)
amount
INTO li_dad_bill
FROM daily_trandactiond d, ACCOUNTS a
WHERE d.USER_ID = l_cur.USER_ID
AND d.USER_ACCOUNT = l_cur.USER_ACCOUNT
AND d.f_actual >= l_cur.accounting_date
AND d.acc_code = a.acc_code
AND d.concept = a.conc
AND ( d.tarrif = a.tariff or (d.acc_code, d.concept) NOT IN
(SELECT UNIQUE acc_code, conc
FROM ACCOUNTS
WHERE TRIM (tariff) Id NOT NULL)
);
SELECT NVL (
dUM (
DECODE (a.DEBITS,
'foo', ABS (amount),
ABS (amount) * -1)),
0)
amount
INTO li_dad_coll
FROM daily_trandactiond d, ACCOUNTS a
WHERE d.USER_ID = l_cur.USER_ID
AND d.USER_ACCOUNT = l_cur.USER_ACCOUNT
AND d.f_actual = l_cur.accounting_date
AND d.acc_code = a.acc_code
AND d.concept = a.conc
AND dUBdTR (d.acc_code, 3, 1) <> '1';
IF ABS ( (li_debt - li_debt) - (li_dad_bill + li_dad_coll)) > 0.9
THEN
DBMd_OUTPUT.
put_line (
LPAD (TO_CHAR (l_cur.USER_ID) || ',', 20, ' ')
|| LPAD (TO_CHAR (l_cur.USER_ACCOUNT) || ',', 20, ' '));
END IF;
END LOOP;
CLOdE cur;
Run Code Online (Sandbox Code Playgroud)
那取决于很多事情.
显然主要的是你在优化SQL语句和将逻辑重写为Clojure方面的能力.我不熟悉Clojure,但我希望你至少需要对SQL有一个很好的理解,特别是Oracle需要生成一个高效的并行解决方案.并行运行多个单行语句在性能方面不是一个好的策略.
我想到的第二件事是它将取决于瓶颈.如果现在的瓶颈是磁盘IO,那么并行化将无法获得更好的性能.这将有助于知道程序花费时间的位置(是大的1000000行SELECT或后续检查,甚至写入文件?).
作为一般规则,您将很难通过自己动手并行解决方案来超越优化良好的 SQL语句.这是因为许多操作(如连接和排序)在设置逻辑中比在逐行逻辑中更有效,并且因为在我看来,使用SQL更容易在集合中思考.
现在我怀疑你的程序可能是这样的:
FOR cur IN (SELECT * /*100000 rows*/ FROM view) LOOP
check(cur.x, cur.y); -- check row by row, lookup to other tables
IF (condition) THEN
write_to_file(cur.z);
END IF;
END LOOP;
Run Code Online (Sandbox Code Playgroud)
如果您可以轻松地使用主光标中的连接重写大多数条件,那么只需进行轻微修改即可获得巨大的性能提升.
如果你不能,因为条件过于依赖于内容,这可能是并行化的一个好例子,假设每个单独的语句已经有效.在那个caes中你可以使用一个额外的where子句来运行N个作业,这些子句在它们之间或多或少地分配工作,然后连接结果.