优化PL/SQL或迁移到Clojure(可并行语言)?

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)

Vin*_*rat 5

那取决于很多事情.

显然主要的是你在优化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个作业,这些子句在它们之间或多或少地分配工作,然后连接结果.