開發為了邏輯清晰大量使用 WITH 子句(子查詢因子化),將中間結果集緩存。但優化器無法將外層謂詞下推到 WITH 定義的內部視圖,導致索引失效、全表掃描。實測優化前 2+ 小時,改寫後 12 秒。
建測試表與索引:
DROP TABLE test PURGE;
CREATE TABLE test AS SELECT * FROM dba_objects;
CREATE INDEX ind_t_object_id ON test(object_id) NOLOGGING;
EXEC dbms_stats.gather_table_stats(USER, 'test', cascade => TRUE);
WITH a AS (SELECT * FROM test WHERE object_type='TABLE'),
b AS (SELECT COUNT(1) FROM a WHERE object_id < 10),
c AS (SELECT COUNT(1) FROM a WHERE object_id >= 10 AND object_id < 20)
SELECT (SELECT * FROM b) bc, (SELECT * FROM c) cc FROM dual;
執行計劃關鍵點:
SYS_TEMP_0FD9D66 存儲 a 的結果(1600 行)。b、c 對臨時表做 FULL TABLE SCAN 過濾 object_id,索引 ind_t_object_id 完全未使用。WITH b AS (SELECT COUNT(1) FROM test WHERE object_id < 10),
c AS (SELECT COUNT(1) FROM test WHERE object_id >= 10 AND object_id < 20)
SELECT (SELECT * FROM b) bc, (SELECT * FROM c) cc FROM dual;
執行計劃關鍵點:
test 表做 INDEX RANGE SCAN(object_id 範圍)。WITH 子句會物化中間結果(TEMP TABLE TRANSFORMATION),阻斷謂詞下推。/*+ INLINE */ 提示嘗試內聯,或改用視圖/內聯視圖。