一般認知中,DISTINCT 意味著排序去重,會增加 CPU 與臨時表空間開銷。但實戰案例發現:某複雜查詢加上 DISTINCT 後,執行時間從 10+ 分鐘降至 4 分鐘。經驗證,DISTINCT 位於最外層,非子查詢。
CREATE TABLE t1 AS SELECT * FROM dba_objects WHERE owner='SYS' AND object_type NOT LIKE '%BODY' AND object_type NOT LIKE 'Java%';
CREATE TABLE t2 AS SELECT * FROM dba_segments WHERE owner='SYS';
CREATE TABLE t3 AS SELECT * FROM dba_indexes WHERE owner='SYS';
ALTER TABLE t1 ADD CONSTRAINT pk_t1 PRIMARY KEY (object_name);
CREATE INDEX ind_t2_segname ON t2(segment_name);
CREATE INDEX ind_t3_tabname ON t3(table_name);
-- 統計資訊收集含直方圖
SELECT t1.object_name, t1.object_type, t2.tablespace_name
FROM t1, t2
WHERE t1.object_name = t2.segment_name
AND t1.object_name IN (SELECT index_name FROM t3 WHERE t3.tablespace_name = t2.tablespace_name);
SELECT DISTINCT t1.object_name, t1.object_type, t2.tablespace_name
FROM t1, t2
WHERE t1.object_name = t2.segment_name
AND t1.object_name IN (SELECT index_name FROM t3 WHERE t3.tablespace_name = t2.tablespace_name);
| 場景 | 連接方式 | 特性 |
|---|---|---|
| 無 DISTINCT + IN 子查詢 | HASH JOIN SEMI | 半連接:只需找到第一個匹配即停止,但需構建雜湊表並探測,對大結果集開銷較大 |
| 有 DISTINCT | HASH JOIN (標準) | 標準雜湊連接:一次掃描建構雜湊表,再探測,無「首匹配即停」邏輯,對大量輸入反而更高效 |
優化器預見最終需 SORT UNIQUE,傾向選擇標準 HASH JOIN 產生已部分有序的中間結果,減少後續排序成本;同時避開 SEMI JOIN 的重複探測開銷。
優化沒有絕對真理,「死規則」會誤事。理解優化器成本模型與連接機制,結合具體數據分佈、約束條件、業務語意,才能做出正確抉擇。此案例旨在拋磚引玉,非提供通用調優手法。