SELECT * FROM v_view WHERE owner_id = 123 往往無法將 owner_id 推入各子查詢,導致全表掃描後再過濾。ship_base_info 出現 4 次),IO 放大數十倍。CREATE OR REPLACE PROCEDURE get_shipowner_report(
p_owner_id IN NUMBER,
p_cursor OUT SYS_REFCURSOR
) AS
BEGIN
OPEN p_cursor FOR
WITH base AS (
SELECT owner_id, COUNT(*) cnt, SUM(dwt) dwt_sum, SUM(cgt) cgt_sum
FROM ship_base_info
WHERE owner_id = p_owner_id -- 謂詞下推到最底層
GROUP BY owner_id
),
new_orders AS (
SELECT owner_id, COUNT(*) cnt, SUM(dwt) dwt_sum
FROM order_info_new
WHERE owner_id = p_owner_id
AND contract_date >= TRUNC(SYSDATE, 'YYYY')
GROUP BY owner_id
)
-- 以此類推,最後 JOIN 各 CTE
SELECT ...
FROM base
LEFT JOIN new_orders USING (owner_id)
...;
END;
優點:參數化 讓優化器產生最佳計劃、CTE 避免重複掃描、單一掃描 替代多子查詢。
CREATE MATERIALIZED VIEW mv_shipowner_report
BUILD IMMEDIATE
REFRESH FAST ON COMMIT -- 或排程 REFRESH COMPLETE
ENABLE QUERY REWRITE
AS SELECT ...; -- 同原視圖 SQL
-- 必須建立 MV LOG
CREATE MATERIALIZED VIEW LOG ON ship_base_info WITH ROWID, SEQUENCE (owner_id, dwt, cgt) INCLUDING NEW VALUES;
-- 其他表同理
查詢直接讀取預先計算結果,毫秒級回應。
owner_id、ship_owner_id、sellers_id、buyer_id 建立 B-tree 索引contract_date、ship_business_date 建立索引,配合 TRUNC(SYSDATE, 'YYYY') 使用函數索引(owner_id, contract_date) 覆蓋「特定船東當年新造船」查詢EXPLAIN PLAN FOR SELECT * FROM v_shipowner_all_test WHERE owner_id = 123;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
-- 關注:FULL TABLE SCAN、CARDINALITY 偏差、JOIN METHOD (NESTED LOOPS vs HASH JOIN)