2012-07-27 53 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