SELECT t1.member_id ,
SUM(t1.paid_amt) AS paid_amt
FROM
(SELECT DISTINCT fm.member_id,
fc.claim_skey_no,
fc.claim_id,
fc.claim_line_no ,
CASE
WHEN fc.claim_type_cd = 'RX'
THEN NVL(fc.rx_paid_amt,0) -- For RX claims use rx_paid_amt as paid amount
ELSE NVL(fc.approved_amt,0)
END AS paid_amt -- For all other claims use approved_amt
,
CASE
WHEN fc.claim_type_cd = 'RX'
THEN fc.submit_dt --For RX claims use submit_dt as paid date
ELSE NVL(fc.paid_dt,NVL(fc.edi_eob_dt,NVL(fc.eob_run_dt,fc.outsource_vndr_paid_dt)))
END AS paid_dt --For all other claims use paid_dt
FROM dwprod.fct_claim fc ,
dwprod.fct_member fm
WHERE fc.mbr_skey_no = fm.member_skey_no
-- The service_from_dt on the claim must be between the reimbursement time period.
AND fc.service_from_dt BETWEEN '31-MAY-2013' AND '30-Jun-2014'
-- The follwong 2 conditions make sure that the calims selected are final-status (unadjusted)
-- For non-RX claims, the adjust_type_cd must be Null and the dw_backout_tag must be Null or 'N'
-- For RX claims only the dw_backout_tag must be Null or 'N', the adjust_type_cd is ignored
AND
CASE
WHEN fc.claim_type_cd = 'RX'
THEN 1
WHEN fc.claim_type_cd <> 'RX'
AND fc.adjust_type_cd IS NULL
THEN 1
ELSE 0
END = 1
AND NVL(fc.dw_backout_tag,'N') = 'N'
-- The claim must be in an 'Approved' status, indicated by a status_type_cd = 'A'
AND fc.status_type_cd = 'A'
-- QNXT claims must be in a 'PAID' status
-- Non QNXT claims in the warehouse are assumed to be paid - There are no pended RX claims.
AND
CASE
WHEN fc.dw_source_cd <> 'QNXT'
THEN 1
WHEN fc.dw_source_cd = 'QNXT'
AND fc.last_status_nm = 'PAID'
THEN 1
ELSE 0
END = 1
-- Dental claims are excluded
AND fc.dw_source_cd <> 'DBP'
-- Excludes any Medicare Non-RCI claims
AND
CASE
WHEN NVL(fc.program_nm,'OTHER') = 'MEDICAID'
AND NVL(fc.enroll_ratecode,'RCI') IN ('RCII','RCV','RCVII')
THEN 0
ELSE 1
END = 0
-- It Fits! claims are excluded
AND NVL(fc.expense_cat_nm,'Other') <> 'FITNESS'
AND NVL(fc.proc1_skey_no,12345) NOT IN (21586,21588,21589)
--
AND
CASE
WHEN NVL(fc.program_nm,'OTHER') = 'MEDICAID'
AND NVL(fc.enroll_ratecode,'RCI') IN ('RCII','RCV','RCVII')
THEN 1
WHEN EXISTS
(SELECT 1
FROM dwprod.fct_member_enroll me
WHERE fm.member_skey_no = me.mbr_skey_no
AND fc.service_from_dt BETWEEN me.segment_effect_dt AND me.segment_term_dt
AND me.program_nm = 'MEDICAID'
AND me.enroll_ratecode IN ('RCII','RCV','RCVII')
)
THEN 1
ELSE 0
END = 1
) t1
--Where t1.paid_dt < '31-JAN-2014'
GROUP BY t1.member_id
HAVING SUM(t1.paid_amt) > 175000
回答
運行解釋計劃以查看導致放緩的原因。從我的頭頂,這是什麼「殺」你:
WHEN EXISTS
(SELECT 1
FROM dwprod.fct_member_enroll me
WHERE fm.member_skey_no = me.mbr_skey_no
AND fc.service_from_dt BETWEEN me.segment_effect_dt AND me.segment_term_dt
AND me.program_nm = 'MEDICAID'
AND me.enroll_ratecode IN ('RCII','RCV','RCVII')
)
看看你是否能以某種方式改變這種邏輯存在的東西具有更好的性能。解釋計劃是必須的!
我同意一個解釋計劃會大大幫助解決這個性能問題。如果沒有這些,我會猜想問題的另一部分是謂詞太複雜,甲骨文無法正確估計。這導致基數估計較差,ROWS = 1,其中有數百或數十億行返回。然後導致NESTED LOOP而不是HASH JOIN。有了這樣複雜的謂詞,可能不會有一個好方法將優化器推向正確的方向。這可能需要像'/ * + use_hash(fc fm)full(fc)full(fm)* /'這樣的提示。 –
我同意!在解釋計劃之後,您可以看到優化器的功能,然後使用Oracle提示來提高性能。我看到優化器做了很不合理的決定(完全是嵌套循環而不是散列連接),並且一個簡單的提示已經將查詢從大約30分鐘改善到了大約1分鐘... – Koshera
FROM dwprod.fct_claim fc ,
dwprod.fct_member fm
WHERE fc.mbr_skey_no = fm.member_skey_no
這個交叉連接實際上是一個內部連接。我不能說甲骨文是否會優化這一點,但我們沒有理由不使自己的工作更輕鬆:
FROM dwprod.fct_claim fc ,
INNER JOIN dwprod.fct_member fm
ON fc.mbr_skey_no = fm.member_skey_no
我更喜歡ANSI語法,並且相信它會提高性能從長遠來看,通過使查詢更易於理解和調試。但對於這個具體的陳述,我認真地懷疑這將有助於表現。無論如何,Oracle將大多數ANSI語法轉換爲舊式語法。 –
我更喜歡ANSI,但不是在12c中,因爲使用這種方式有一個開放的錯誤。由於12c在外連接方面有一些增強,與舊版本相比,SQL的處理方式不同。看這裏http://stackoverflow.com/questions/19686262/query-featuring-outer-joins-behaves-differently-in-oracle-12c – SriniV
我會做一個半盲猜這裏,基於DW I」類似的查詢與...合作。 Oracle的優化被容易被混淆的謂詞如:
where (case when ... then ... else ... end) = 1;
的原因是,甲骨文在嚴重估計選擇性。 像其他人說的那樣查看解釋計劃。如果您發現表dwprod.fct_claim
的估計基數看起來太低,請嘗試展開case語句。
例如,而不是:
AND CASE WHEN fc.dw_source_cd <> 'QNXT' THEN 1
WHEN fc.dw_source_cd = 'QNXT' AND fc.last_status_nm = 'PAID' THEN 1
ELSE 0
END = 1
寫:
and ( fc.dw_source_cd <> 'QNXT'
or (fc.dw_source_cd = 'QNXT' and fc.last_status_nm = 'PAID')
)
最後說明。這在版本11中似乎不太成問題,但我還沒有時間去調查原因。
- 1. 查詢運行速度太慢
- 2. Oracle - 查詢運行速度很慢
- 3. 查詢查詢運行速度比直接查詢慢 - 在Oracle
- 4. CoreNLP運行速度太慢
- 5. MySQL查詢速度太慢或超時
- 6. Parse.com查詢速度太慢,需要更快
- 7. 如何優化運行速度太慢的查詢(LEFT JOIN)
- 8. 查詢運行速度非常慢
- 9. SharePoint庫查詢運行速度很慢
- 10. 查詢運行速度很慢
- 11. SSRS SQL查詢運行速度慢
- 12. MySQL中運行速度慢的查詢
- 13. 合併查詢運行速度很慢
- 14. 加入Oracle時查詢速度慢,分裂成兩個查詢時速度快
- 15. Linq查詢運行緩慢,但查詢運行速度很快
- 16. 的MySQL查詢速度太慢
- 17. 實體框架查詢速度太慢
- 18. R循環運行速度太慢
- 19. java - system.nanoTime()運行速度太慢
- 20. 函數運行速度太慢
- 21. Grails標準運行速度太慢
- 22. CROSS APPLY運行速度太慢 - TSQL
- 23. Oracle Bind查詢速度很慢
- 24. SQL查詢在大數據集上運行但速度很慢?
- 25. Oracle:複雜查詢的查詢速度非常快,查詢速度非常慢
- 26. Matlab執行速度太慢
- 27. PHP查詢加載速度太慢。如何加快速度?
- 28. 程序運行速度太慢,輸入較大 - C
- 29. 慢速查詢...需要更快
- 30. SQLite查詢比MSAccess查詢運行速度慢10倍
我試過用這個(FROM dwprod.fct_claim fc,INNER JOIN dwprod.fct_member fm ON fc.mbr_skey_no = fm.member_skey_no)仍然需要很長時間。 – user3357343
您是否檢查了EXPLAIN PLAN?如果不是,爲什麼不呢? –
儘管對您的問題沒有多大意義,但'AND FC.SERVICE_FROM_DT BETWEEN '31 -MAY-2013'和'30 -JUN-2014''應該是AND AND FC.SERVICE_FROM_DT之間的TO_DATE('31 -MAY-2013' ,'DD-MON-YYYY')和TO_DATE('30 -JUN-2014','DD-MON-YYYY')' – SriniV