我在一組SQL中存在性能問題,無法實時生成當前月份的報表。Oracle SQL月度對賬單生成
客戶將使用來自在線系統的點數購買一些商品,並且應該生成包含「open_balance」,「point_earned」,「point_used」,「current_balance」的語句。
下面顯示了縮短模式:
//~200k records
customer: {account_id:string, create_date:timestamp, bill_day:int} //totally 14 fields
//~250k records per month, kept for 6 month
history_point: {point_id:long, account_id:string, point_date:timestamp, point:int} //totally 9 fields
//each customer have maximum of 12 past statements kept
history_statement: {account_id:string, open_date:date, close_date:date, open_balance:int, point_earned:int, point_used:int, close_balance:int} //totally 9 fields
在每個賬單日,視圖會自動創建一個新的一個月的語句。 即如果bill_day爲15,那麼2013年12月16日或之後完成的交易00:00:00應該屬於2013年12月16日的新帳單週期00:00:00 - 2014年1月15日23:59:59
I試圖
- 計算每個帳戶的最後收市下面所描述的方法,(在物化視圖,使其僅更新後有插入history_statement新客戶或過去的一個月中陳述)
- 生成一個記錄每個客戶每個月我需要計算(也在物化視圖中)
- 篩分點rec ord僅用於計算日期內的點記錄(這隻需要〜0.1s)
- 加入2與3以獲得積分並用於每個客戶每月
- 加入4與4日期少於打開日期到期末餘額 6a。從開始日期小於1個月大的地方開始選擇5作爲當前餘額(這些還沒有關閉,並且該點反映了每個客戶擁有的點數) 6b。所有的陳述都是通過history_statement和union聯合獲得的5
在開發服務器上,平均響應時間(200K客戶,當月1.5M的交易)測試服務器的資源可能會被共享,平均響應時間(20萬客戶,每月約8萬個交易約20萬次)爲10-15秒。
有沒有人有更好的方法來編寫查詢或加快查詢的一些想法?
相關SQL:
2:IV_STCLOSE_2_1_T(物化視圖)
3:IV_STCLOSE_2_2_T(〜0.15秒)
SELECT ACCOUNT_ID, POINT_DATE, POINT
FROM history_point
WHERE point_date >= (
SELECT MIN(open_date)
FROM IV_STCLOSE_2_1_t
)
4:IV_STCLOSE_3_T(〜1.5秒)
SELECT p0.account_id, p0.open_date, p0.close_date, COALESCE(SUM(DECODE(SIGN(p.point),-1,p.point)),0) AS point_used, COALESCE(SUM(DECODE(SIGN(p.point),1,p.point)),0) AS point_earned
FROM iv_stclose_2_1_t p0
LEFT JOIN iv_stclose_2_2_t p
ON p.account_id = p0.account_id
AND p.point_date >= p0.open_date
AND p.point_date < p0.close_date + INTERVAL '1' DAY
GROUP BY p0.account_id, p0.open_date, p0.close_date
5:IV_STCLOSE_4_T(〜3s)
WITH t AS (SELECT * FROM IV_STCLOSE_3_T)
SELECT t1.account_id AS STAT_ACCOUNT_ID, t1.open_date, t1.close_date, t1.open_balance, t1.point_earned AS point_earn, t1.point_used , t1.open_balance + t1.point_earned + t1.point_used AS close_balance
FROM (
SELECT v1.account_id, v1.open_date, v1.close_date, v1.point_earned, v1.point_used, COALESCE(sum(v2.point_used + v2.point_earned),0) AS OPEN_BALANCE
FROM t v1
LEFT JOIN t v2
ON v1.account_id = v2.account_id
AND v1.OPEN_DATE > v2.OPEN_DATE
GROUP BY v1.account_id, v1.open_date, v1.close_date, v1.point_earned, v1.point_used
) t1
一些備註:1)它可能會幫助,看看實際的查詢中使用2)你應該運行'EXPLAIN PLAN「,並顯示該命令的結果 – fvu
@fvu相關策略的SQL位於該帖子的底部。 – kftse