0

我正在开发一个 MVC 3 项目,其中一些报告将在代码中生成 SQL 查询,然后在 Oracle 10g 数据库上执行它们。另外,我了解 SQL 注入攻击,所有值都来自下拉列表,而不是文本输入,所以这不是问题。我生成的查询“工作”,但它们非常慢。以下是该报告如何工作的简要说明:

用户选择了总帐帐户和其他过滤器。用户选择了一个时间段(财政年度、季度或特定月份)。用户运行报告。

该报告显示总帐帐户(或帐户,如果选择显示所有帐户)和每个月花费的值以及该帐户的总额。查询的输出将如下所示:

帐号和姓名 | 第 1 个月 | 第 2 个月 | 等| 全部的

第 1 个月、第 2 个月等是在生成 SQL 代码时动态添加的,因此根据用户选择的内容,可能会或可能不会在结果集中返回。我该怎么做才能使这个查询更快?当我昨天对整个财政年度(并且只有 1 个帐户)运行此查询时,它需要 10 分钟才能完成。我不认为这是可以接受的性能,并希望使其更快。请记住,我只能对查询本身进行更改,而不是对数据库进行更改,因此不会发生索引(DBA 会锁定所有内容)。查询如下。感谢大家对此提供的任何意见。

SELECT gl.gen_led_acct_nbr, gl.gen_led_acct_scr_nm, bu.bus_unit_txt, gl.gen_led_acct_typ_nm,
  (SELECT SUM(fct.pd_txn_amt) Jun2012
FROM Maintable fct
JOIN Dimtable1 gl1 ON fct.gen_led_acct_key = gl1.gen_led_acct_key
JOIN Dimtable2 bu1 ON fct.bus_unit_key = bu1.bus_unit_key
JOIN Dimtable3 cc1 ON fct.cst_ctr_key = cc1.cst_ctr_key
JOIN Dimtable4 oc1 ON fct.cst_ctr_own_org_key = oc1.org_cd_key
JOIN Dimtable5 dt1 ON fct.chk_dt_key          = dt1.dt_key
WHERE gl1.gen_led_acct_nbr = gl.gen_led_acct_nbr
  AND bu1.bus_unit_txt       = bu.bus_unit_txt
  AND dt1.fscl_mo_nbr        = 1
  AND dt1.fscl_yr_nbr        = 2012
  GROUP BY gl1.gen_led_acct_nbr, gl1.gen_led_acct_scr_nm, bu1.bus_unit_txt) Jun2012,
(SELECT SUM(fct.pd_txn_amt) Jun2012
FROM Maintable fct
JOIN Dimtable1 gl2 ON fct.gen_led_acct_key = gl2.gen_led_acct_key
JOIN Dimtable2 bu2 ON fct.bus_unit_key = bu2.bus_unit_key
JOIN Dimtable3 cc2 ON fct.cst_ctr_key = cc2.cst_ctr_key
JOIN Dimtable4 oc2 ON fct.cst_ctr_own_org_key = oc2.org_cd_key
JOIN Dimtable5 dt2 ON fct.chk_dt_key          = dt2.dt_key
WHERE gl2.gen_led_acct_nbr = gl.gen_led_acct_nbr
  AND bu2.bus_unit_txt       = bu.bus_unit_txt
  AND dt2.fscl_mo_nbr        = 2
  AND dt2.fscl_yr_nbr        = 2012
  GROUP BY gl2.gen_led_acct_nbr, gl2.gen_led_acct_scr_nm, bu2.bus_unit_txt) Jul2012,

(etc...)
--The sub queries above can be repeated up to an indefinite amount of times (maybe 20+), but with a different fscl_mo_nbr (and possibly fscl_yr_nbr as well)

FROM Maintable fct
JOIN Dimtable1 gl ON fct.gen_led_acct_key = gl.gen_led_acct_key
JOIN Dimtable2 bu ON fct.bus_unit_key = bu.bus_unit_key
JOIN Dimtable3 cc ON fct.cst_ctr_key = cc.cst_ctr_key
JOIN Dimtable4 oc ON fct.cst_ctr_own_org_key = oc.org_cd_key
JOIN Dimtable5 dt ON fct.chk_dt_key         = dt.dt_key
WHERE gl.gen_led_acct_nbr = 000000
  AND bu.bus_unit_txt       = 'AAAAA'
  AND dt.fscl_mo_nbr        = 1
  AND dt.fscl_yr_nbr        = 2012
GROUP BY gl.gen_led_acct_nbr, gl.gen_led_acct_scr_nm, bu.bus_unit_txt, gl.gen_led_acct_typ_nm
ORDER BY gl.gen_led_acct_nbr, gl.gen_led_acct_typ_nm
4

1 回答 1

1

你的评论:

--The sub query above can be repeated up to another 11 times, but with a different dt1.fscl_mo_nbr

建议一种解决方案是使用“in”而不是“=”,如:

AND dt1.fscl_mo_nbr        in (1, 2, . . . )

然后,您需要将 t1.fscl_mo_nbr 添加到 group by 子句。

我还注意到这是一个很大的相关子查询,这可能也会影响性能。像下面这样的东西应该可以简化查询并帮助它运行得更快:

SELECT gl.gen_led_acct_nbr, gl.gen_led_acct_scr_nm, bu.bus_unit_txt, 
       gl.gen_led_acct_typ_nm,
       sum(case when year = 2012 and dt.fscl_mo_nbr = 1 then fct.pd_txn_amt end) as Jun2012,
       sum(case when year = 2012 and dt.fscl_mo_nbr = 2 then fct.pd_txn_amt end) as Jul2012,
        etc. 
      FROM Maintable fct
           JOIN Dimtable1 gl ON fct.gen_led_acct_key = gl.gen_led_acct_key
           JOIN Dimtable2 bu ON fct.bus_unit_key = bu.bus_unit_key
           JOIN Dimtable3 cc ON fct.cst_ctr_key = cc.cst_ctr_key
           JOIN Dimtable4 oc ON fct.cst_ctr_own_org_key = oc.org_cd_key
           JOIN Dimtable5 dt ON fct.chk_dt_key          = dt.dt_key
       where dt.fscl_mo_nbr  in (1, 2, 3 . . .)
            AND dt.fscl_yr_nbr  = 2012
       GROUP BY gl.gen_led_acct_nbr, gl.gen_led_acct_scr_nm,
                bu.bus_unit_txt, dt.fscl_mo_nbr

(请原谅任何打字错误......我从所有别名中删除了“1”后缀。)

于 2012-07-27T13:40:06.727 回答