首页 > 解决方案 > 如何优化这个复杂的查询?

问题描述

我正在运行具有很多条件的复杂查询。在大型数据库上,查询需要 2 分钟以上。我正在为我的项目使用 Django。我可以优化这个查询吗?或者我应该使用 Django ORM 查询?哪个更快?LN_ACCOUNT 表的行数超过 300 万行。任何建议和帮助将不胜感激。太感谢了。

SELECT COUNT(*), SUM((select sum(acc.SALDO_EQUIVAL_OUT)
  from LN_ACCOUNT lna, ACCOUNTS acc
  where lna.LOAN_ID = L.LOAN_ID
  and lna.LOAN_TYPE_ACCOUNT in ('1','4','5','8')
  and lna.DATE_NEXT > '21.11.2020'
  and lna.DATE_VALIDATE <= '20.11.2020'
  and acc.CODE = lna.ACCOUNT_CODE
  and (substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
      or (
              select 'Y' from
              V_REP_LN_BAL v
              where v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
              and ROWNUM = 1
          ) = 'Y'
      )))/-100
FROM LN_CARD L
and
    L.LOAN_ID IN (
                  select distinct (LOAN_ID) LID
                  from (
                           select (
                                      select LOAN_ID
                                      from LN_ACCOUNT s
                                      where s.ACCOUNT_CODE = ac.CODE
                                        and s.DATE_NEXT > '21.11.2020'
                                        and s.DATE_VALIDATE <= '21.11.2020'
                                        and rownum = 1) as LOAN_ID
                           from ACCOUNTS ac,
                                V_REP_LN_BAL vr
                           where vr.BAL_ACC = ac.CODE_COA
                             and vr.TYPE_BAL in (1, 2, 3, 4)
                       ) lnIDS
                  where LOAN_ID is not null)
and (
  select sum(abs(acc.SALDO_EQUIVAL_OUT))
  from LN_ACCOUNT lna, ACCOUNTS acc
  where lna.LOAN_ID = l.LOAN_ID
  and lna.LOAN_TYPE_ACCOUNT in ('1','4','5','8')
  and lna.DATE_NEXT > '21.11.2020'
  and lna.DATE_VALIDATE <= '21.11.2020'
  and acc.CODE = lna.ACCOUNT_CODE
  and (substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
      or (
              select 'Y' from
              V_REP_LN_BAL v
              where v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
              and ROWNUM = 1
          ) = 'Y'
      )
  )
      + abs(
          NVL((select sum(acc.SALDO_EQUIVAL_OUT)
                  from LN_ACCOUNT lna, ACCOUNTS acc
                  where lna.LOAN_ID = l.LOAN_ID
                  and lna.LOAN_TYPE_ACCOUNT = 3
                  and lna.DATE_NEXT > '21.11.2020'
                  and lna.DATE_VALIDATE <= '21.11.2020'
                  and acc.CODE = lna.ACCOUNT_CODE
                  and (substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
                  or  (select 'Y' from
                     V_REP_LN_BAL v
                      where v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
                      and ROWNUM = 1) = 'Y'
                  )),0) +
          NVL((select sum(acc.SALDO_EQUIVAL_OUT)
                  from LN_ACCOUNT lna, ACCOUNTS acc
                  where lna.LOAN_ID = l.LOAN_ID
                  and lna.LOAN_TYPE_ACCOUNT = 7
                  and lna.DATE_NEXT > '21.11.2020'
                  and lna.DATE_VALIDATE <= '21.11.2020'
                 and acc.CODE = lna.ACCOUNT_CODE
                  and (substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
                  or  (select 'Y' from
                      V_REP_LN_BAL v
                      where v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
                      and ROWNUM = 1) = 'Y'
                  )),0) +
          NVL((select sum(acc.SALDO_EQUIVAL_OUT)
                  from LN_ACCOUNT lna, ACCOUNTS acc
                  where lna.LOAN_ID = l.LOAN_ID
                  and lna.LOAN_TYPE_ACCOUNT = 79
                  and lna.DATE_NEXT > '21.11.2020'
                  and lna.DATE_VALIDATE <= '21.11.2020'
                  and acc.CODE = lna.ACCOUNT_CODE
                  and (substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
                  or  (select 'Y' from
                      V_REP_LN_BAL v
                      where v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
                      and ROWNUM = 1) = 'Y'
                  )),0)
          )
      + abs(NVL((select sum(acc.SALDO_EQUIVAL_OUT)
                  from LN_ACCOUNT lna, ACCOUNTS acc
                  where lna.LOAN_ID = l.LOAN_ID
                  and lna.LOAN_TYPE_ACCOUNT = 46
                  and lna.DATE_NEXT > '21.11.2020'
                  and lna.DATE_VALIDATE <= '21.11.2020'
                  and acc.CODE = lna.ACCOUNT_CODE
                  and (substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
                  or  (select 'Y' from
                      V_REP_LN_BAL v
                      where v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
                      and ROWNUM = 1) = 'Y'
                  )),0))
      + abs(
          NVL((select sum(acc.SALDO_EQUIVAL_OUT)
                  from LN_ACCOUNT lna, ACCOUNTS acc
                  where lna.LOAN_ID = l.LOAN_ID
                  and lna.LOAN_TYPE_ACCOUNT = 6
                  and lna.DATE_NEXT > '21.11.2020'
                  and lna.DATE_VALIDATE <= '21.11.2020'
                  and acc.CODE = lna.ACCOUNT_CODE
                  and (substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
                  or  (select 'Y' from
                      V_REP_LN_BAL v
                      where v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
                      and ROWNUM = 1) = 'Y'
                  )),0) +
          NVL((select sum(acc.SALDO_EQUIVAL_OUT)
                  from LN_ACCOUNT lna, ACCOUNTS acc
                  where lna.LOAN_ID = l.LOAN_ID
                  and lna.LOAN_TYPE_ACCOUNT = 52
                  and lna.DATE_NEXT > '21.11.2020'
                  and lna.DATE_VALIDATE <= '21.11.2020'
                  and acc.CODE = lna.ACCOUNT_CODE
                  and (substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
                  or  (select 'Y' from
                      V_REP_LN_BAL v
                      where v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
                      and ROWNUM = 1) = 'Y'
                  )),0) +
          NVL((select sum(acc.SALDO_EQUIVAL_OUT)
                  from LN_ACCOUNT lna, ACCOUNTS acc
                  where lna.LOAN_ID = l.LOAN_ID
                  and lna.LOAN_TYPE_ACCOUNT = 53
                 and lna.DATE_NEXT > '21.11.2020'
                  and lna.DATE_VALIDATE <= '21.11.2020'
                  and acc.CODE = lna.ACCOUNT_CODE
                  and (substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
                  or  (select 'Y' from
                      V_REP_LN_BAL v
                      where v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
                      and ROWNUM = 1) = 'Y'
                  )),0) +
          NVL((select sum(acc.SALDO_EQUIVAL_OUT)
                  from LN_ACCOUNT lna, ACCOUNTS acc
                  where lna.LOAN_ID = l.LOAN_ID
                  and lna.LOAN_TYPE_ACCOUNT = 54
                  and lna.DATE_NEXT > '21.11.2020'
                  and lna.DATE_VALIDATE <= '21.11.2020'
                  and acc.CODE = lna.ACCOUNT_CODE
                  and (substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
                  or  (select 'Y' from
                      V_REP_LN_BAL v
                      where v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
                      and ROWNUM = 1) = 'Y'
                  )),0)
          ) <> 0;

标签: sqldatabaseoraclequery-performancesqlperformance

解决方案


您正在执行多个嵌套子查询:

+ abs(
  NVL((select sum(acc.SALDO_EQUIVAL_OUT)
       from   LN_ACCOUNT lna, ACCOUNTS acc
       where lna.LOAN_ID = l.LOAN_ID
       and   lna.LOAN_TYPE_ACCOUNT = 3
       and   lna.DATE_NEXT > '21.11.2020'
       and   lna.DATE_VALIDATE <= '21.11.2020'
       and   acc.CODE = lna.ACCOUNT_CODE
       and   ( substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
               or  (select 'Y'
                    from   V_REP_LN_BAL v
                    where  v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
                    and    ROWNUM = 1
                   ) = 'Y'
             )
     ),
     0
   )

唯一的区别似乎是lna.LOAN_TYPE_ACCOUNT您正在过滤。连接所有这些,以便您只需要查询一次表:

+ COALESCE(
    (
      SELECT SUM( t.abs_total )
      FROM   (
        SELECT lna.LOAN_ID,
               lna.LOAN_TYPE_ACCOUNT,
               ABS( SUM( acc.SALDO_EQUIVAL_OUT ) ) AS abs_total
        FROM   LN_ACCOUNT lna
               INNER JOIN ACCOUNTS acc
               ON ( acc.CODE = lna.ACCOUNT_CODE )
        WHERE  lna.LOAN_TYPE_ACCOUNT IN ( 3, 7, 79, 46, 6, 52, 53, 54 )
        AND    lna.DATE_NEXT > DATE '2020-11-21'
        AND    lna.DATE_VALIDATE <= DATE '2020-11-21'
        AND    (    substr(lna.ACCOUNT_CODE, -20, 3) in ('163','915')
                 OR EXISTS( SELECT 1
                            FROM   V_REP_LN_BAL v
                            WHERE  v.BAL_ACC like substr(lna.ACCOUNT_CODE, -20, 3)||'%'
                          )
               )
        GROUP BY
               lna.LOAN_ID,
               lna.LOAN_ACCOUNT_TYPE
      ) t
      WHERE    t.LOAN_ID = l.LOAN_ID
    ),
    0
  )

LOAN_TYPE_ACCOUNT在使用之前,您需要检查以确保您仍然获得与似乎聚合多个相同的结果ABS;但是,如果是这种情况,那么LOAN_TYPE_ACCOUNTSELECT可以GROUP BY使用:

CASE 
WHEN LOAN_TYPE_ACCOUNT IN (  3,  7, 79     ) THEN 'Group1'
WHEN LOAN_TYPE_ACCOUNT IN ( 46             ) THEN 'Group2'
WHEN LOAN_TYPE_ACCOUNT IN (  6, 52, 53, 54 ) THEN 'Group3'
END

推荐阅读