首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle SQL 效能調優實戰精華:WHERE 順序、索引陷阱、改寫技巧與執行計畫分析

     編輯:Oracle 資料庫基礎

前言

SQL 語句效能決定系統回應速度。本文蒐羅實戰驗證的調優鐵律:WHERE 條件順序、SELECT * 危害、索引使用六大忌諱、EXISTS/UNION 改寫、ORDER BY 技巧、排序操作避免、WHERE 替代 HAVING、子查詢消除,並附執行計畫分析方法論。

一、解析器運作原理與 WHERE 條件順序

  • Oracle 解析器自下而上處理 WHERE 子句
  • 表連接條件必須寫在最前面
  • 過濾性最強條件 (如主鍵 ID = ?) 寫在最後面
  • 原則:先連接縮小結果集,再過濾精準定位

二、SELECT * 為效能殺手

  • 解析階段需查詢資料字典展開所有欄位名
  • 增加網路傳輸量、客戶端處理開銷
  • 阻礙「覆蓋索引」最佳化
  • 鐵律:明確列出所需欄位

三、索引:優勢、代價與六大使用忌諱

優勢

  • B-Tree 結構,範圍/等值查詢 O(log n)
  • 避免全表掃描,減少磁碟 I/O
  • 主鍵/唯一約束天然建立索引
  • 連接欄位索引大幅加速 Join

代價

  • 儲存空間 (通常表大小 10-30%)
  • DML 維護開銷:每 INSERT/DELETE/UPDATE 額外 4-5 次 I/O
  • 過多索引反而拖慢寫入、誤導優化器

六大索引失效陷阱

#陷阱失效範例修正寫法
1索引欄位用 NOTWHERE status != 'A'WHERE status IN ('B','C','D') 或改用位圖索引
2索引欄位做運算/函數WHERE sal * 12 > 25000WHERE sal > 25000/12
3IS NULL / IS NOT NULLWHERE dept_code IS NOT NULLWHERE dept_code >= 0 (若非負)
4LIKE 導模糊查詢WHERE dept_code LIKE '%123%'WHERE dept_code = '123' 或功能性索引
5隱式型別轉換發生在索引欄WHERE emp_type = 123 (emp_type 是 CHAR)WHERE emp_type = '123' 或 TO_CHAR(123)
6資料量超 30% 表大小大範圍掃描全表掃描反而更快

四、經典改寫模式

1. EXISTS 替代 DISTINCT (一對多去重)

-- 低效
SELECT DISTINCT d.dept_no, d.dept_name
FROM dept d, emp e
WHERE d.dept_no = e.dept_no AND e.sex = 'M';

-- 高效
SELECT d.dept_no, d.dept_name
FROM dept d
WHERE EXISTS (
  SELECT 'X' FROM emp e
  WHERE e.dept_no = d.dept_no AND e.sex = 'M'
);

EXISTS 滿足即停止掃描,避免排序去重。

2. UNION ALL 替代 OR (索引欄位)

-- 低效:OR 導致全表掃描
SELECT loc_id, loc_desc, region FROM location
WHERE loc_id = 10 OR region = 'MELBOURNE';

-- 高效:UNION ALL 合併兩個索引掃描
SELECT loc_id, loc_desc, region FROM location WHERE loc_id = 10
UNION ALL
SELECT loc_id, loc_desc, region FROM location WHERE region = 'MELBOURNE';

前提:loc_id、region 皆有索引。若有欄位無索引,OR 可能更好。

3. UNION ALL 替代 UNION (無需去重時)

  • UNION 需排序去重,佔用 SORT_AREA_SIZE
  • UNION ALL 直接合併,無排序
  • 業務確認無重複資料時,果斷用 UNION ALL

4. ORDER BY 索引欄位 (最好是 PK)

-- 低效:非索引欄位排序
SELECT dept_code FROM dept ORDER BY dept_type;

-- 高效:索引欄位排序 (可避免排序操作)
SELECT dept_code FROM dept ORDER BY dept_code;

5. 避免昂貴排序操作

  • DISTINCT:1 次排序
  • UNION, MINUS, INTERSECT:至少 2 次排序
  • 若 SORT_AREA_SIZE 調優良好,可接受;否則改寫

6. WHERE 替代 HAVING (提前過濾)

-- 低效:分組後再過濾
SELECT job, AVG(sal) FROM emp
GROUP BY job
HAVING job = 'PRESIDENT' AND AVG(sal) > 5000;

-- 高效:分組前過濾
SELECT job, AVG(sal) FROM emp
WHERE job IN ('PRESIDENT','MANAGER')
GROUP BY job
HAVING AVG(sal) > 5000;

7. 消除子查詢 (改為 JOIN 或 EXISTS)

  • 子查詢開銷大:多次掃描、臨時表建立
  • 優化器 10g+ 可自動展開部分子查詢,但複雜案例仍需手工改寫

五、執行計畫分析方法論

獲取計畫

EXPLAIN PLAN FOR SELECT ...;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

-- 或即時計畫 (需權限)
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(sql_id, child_number, 'ALL'));  

關鍵指標解讀

實測驗證

SET TIMING ON
SET AUTOTRACE TRACEONLY STATISTICS
SELECT ...;
-- 觀察: consistent gets, physical reads, sorts, rows processed

六、統計資訊管理:優化器的眼睛

  • DBMS_STATS.GATHER_TABLE_STATS 定期收集 (建議每日/每週)
  • METHOD_OPT => 'FOR ALL COLUMNS SIZE AUTO' 直方圖自動
  • CASCADE => TRUE 同步索引統計
  • 鎖定統計資訊防止倒退:DBMS_STATS.LOCK_TABLE_STATS

結語

SQL 調優沒有銀彈,只有「理解優化器、閱讀執行計畫、驗證實測、持續迭代」。本文 8 大鐵律涵蓋 90% 常見效能問題:條件順序、拒絕 SELECT *、索引六不准、EXISTS 去重、UNION ALL 去 OR/排序、ORDER BY 走索引、WHERE 先於 HAVING、消除子查詢。配合統計資訊管理、執行計畫閱讀能力、AWR/ASH 系統級分析,即可構建從語句級到系統級的完整效能保障體系。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
指標關注點
OperationFULL TABLE SCAN vs INDEX RANGE SCAN vs NESTED LOOPS
Cost相對成本,非絕對時間
Cardinality (Rows)預估行數,與 Actual 對比驗證統計資訊
Bytes資料量,影響記憶體/臨時表空間
Predicate InformationACCESS vs FILTER 謂詞,判斷索引使用效率
NoteDynamic Sampling, Star Transformation, Adaptive Plan 等提示