I’m working on a MVC 3 project where some of the reports will generate the SQL queries in code then executes them on an Oracle 10g database. Also, I understand SQL injection attacks, and all the values are coming from drop down lists, not text inputs, so this is not an issue. My generated queries “work”, but they are extremely slow. Here is a quick run down on how the report works:
User selected a general ledger account and other filters.
User selected a time period (a fiscal year, a quarter or a specific month).
User runs report.
The report shows the general ledger account (or accounts if the select to show all accounts) and the values spent for each month along with a total for that account. The output from the query will look like this:
Account Number and Name | Month 1 | Month 2 | etc | Total
Month 1, Month 2, etc are dynamically added in while the SQL code is being generated, so depending on what the user selects, it may, or may not, be returned in the result set. What can I do to make this query faster? When I ran this query yesterday for the entire fiscal year (and only 1 account), it took 10mins for it to complete. I don’t feel this is acceptable performance, and would like to make it faster. Keep in mind, I can only make changes to the query itself, not the database, so indexing is not going to happen (the DBAs keep everything locked down). The query is below. Thanks for any input you all can provide on this.
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
Your comment:
Suggests that one solution would be to use “in” rather than “=”, as in:
You then would want to add t1.fscl_mo_nbr to the group by clause.
I also notice that this is a big correlated subquery, which is probably also killing performance. Something like the following should simplify the query and help it run faster:
(Please excuse any typing errors . . . I removed the “1” suffix from all the aliases.)