2012-07-27 55 views
0

我正在开发一个MVC 3项目,其中一些报告将在代码中生成SQL查询,然后在Oracle 10g数据库上执行它们。此外,我了解SQL注入攻击,并且所有值都来自下拉列表,而不是文本输入,所以这不是问题。我生成的查询“工作”,但它们非常缓慢。以下是报告运作方式的快速结果:使用子查询优化Oracle查询使用母公司的相同表格

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

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

帐号和名称|第1个月|第2个月| etc |总计

当生成SQL代码时,会动态地添加第1个月,第2个月等,因此根据用户选择的内容,它可能会或可能不会返回结果集中。我能做些什么来使这个查询更快?当我在整个财政年度(并且只有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 

回答

1

您的评论:

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

表明,一个解决办法是 “在”,而不是 “=” 来使用,如:

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”后缀)

+0

我不是确定这将如何工作,因为每个日期都需要是查询返回的结果集中的单独列。 – 2012-07-27 13:41:42

+0

使用SUM和CASE子句修改后的查询看起来确实有点帮助。我在整个2012财年运行了一个稍微修改过的版本,再次申请了1个gl账户,并在21secs完成,而不是昨天花费的10分钟。谢谢你的帮助戈登!对此,我真的非常感激。 – 2012-07-27 14:25:02