0

私はMVC3プロジェクトに取り組んでおり、一部のレポートはコードでSQLクエリを生成し、Oracle10gデータベースで実行します。また、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

次のように、1つの解決策は「=」ではなく「in」を使用することです。

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

次に、t1.fscl_mo_nbrをgroupby句に追加します。

また、これは大きな相関サブクエリであり、おそらくパフォーマンスを低下させていることにも気づきました。次のようなものは、クエリを単純化し、より高速に実行するのに役立ちます。

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 に答える