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

Oracle SQL 效能優化關鍵技巧:IN/NOT IN/<>/IS NULL/LIKE/UNION 改寫指南

     編輯:關於SqlServer

Oracle SQL 優化的核心在於讓優化器選擇索引存取路徑、避免全表掃描、減少排序/雜湊開銷。本文針對常見低效寫法提供具體改寫模式與原理說明。

1. IN 操作符

現象:WHERE col IN (subquery) 可能轉換為半連結,但含分組/聚合的子查詢無法轉換,導致先執行子查詢再外層掃描。

建議:業務核心 SQL 盡量避免 IN,改用 EXISTS 或 JOIN。

-- 低效
SELECT * FROM Orders WHERE CustomerID IN (SELECT CustomerID FROM Customers WHERE Region = 'West');

-- 高效:EXISTS 相關子查詢
SELECT * FROM Orders o WHERE EXISTS (SELECT 1 FROM Customers c WHERE c.CustomerID = o.CustomerID AND c.Region = 'West');

-- 高效:JOIN (需去重)
SELECT DISTINCT o.* FROM Orders o JOIN Customers c ON o.CustomerID = c.CustomerID WHERE c.Region = 'West';

2. NOT IN 操作符 — 強烈建議禁止

原因:NOT IN 遇到子查詢回傳 NULL 時,整個條件永遠為 UNKNOWN,導致結果為空;且無法使用索引。

替代方案:

-- 低效
SELECT * FROM Products WHERE ProductID NOT IN (SELECT ProductID FROM Discontinued);

-- 高效:NOT EXISTS
SELECT * FROM Products p WHERE NOT EXISTS (SELECT 1 FROM Discontinued d WHERE d.ProductID = p.ProductID);

-- 高效:LEFT JOIN + IS NULL
SELECT p.* FROM Products p LEFT JOIN Discontinued d ON p.ProductID = d.ProductID WHERE d.ProductID IS NULL;

3. <> (不等於) 操作符

特性:永遠不使用索引,導致全表掃描。

改寫 (需確認資料分布):

WHERE status <> 0    -- 改為
WHERE status > 0 OR status < 0

WHERE code <> ''     -- 改為
WHERE code > ''      -- 若 code 為非負字串編碼

4. IS NULL / IS NOT NULL

特性:B-tree 索引不儲存 NULL,故 IS [NOT] NULL 通常全表掃描。

改寫:

WHERE col IS NOT NULL   -- 改為
WHERE col > 0           -- 數值型
WHERE col > ''          -- 字串型

-- 或:不允許 NULL,給預設值
ALTER TABLE T MODIFY col DEFAULT 0 NOT NULL;

替代索引**:位圖索引 可索引 NULL,但不適用高併發 OLTP (鎖競爭劇烈),僅適合資料倉儲/低更新表。

5. > / < 操作符優化

同一欄位、同一常數,>= 比 > 可能更優:

-- 假設 A 欄位值分布:30萬=0, 30萬=1, 39萬=2, 1萬=3
WHERE A > 2    -- 優化器先找 =2 的索引項再比較
WHERE A >= 3   -- 直接定位 =3 的索引項,更快

6. LIKE 操作符

前置萬用字元無法用索引:LIKE '%5400%' → 全表掃描。

改寫:若知道前綴模式,拆解為多個前綴比對:

-- 低效
WHERE YY_BH LIKE '%5400%'

-- 高效:已知前綴為 'X' 或 'B'
WHERE YY_BH LIKE 'X5400%' OR YY_BH LIKE 'B5400%'  -- 兩次索引範圍掃描

7. UNION vs UNION ALL

UNION**:合併後排序去重,大量資料可能落磁碟排序。

UNION ALL**:直接合併,**無排序去重**,效能極高。

建議:業務確定無重複或允許重複時,**永遠用 UNION ALL**。

SELECT * FROM CurrentMonthSales
UNION ALL
SELECT * FROM HistorySales;

8. SQL 寫風格影響計畫

同樣功能,不同寫法可能產生不同計畫。建議:

  • 統一團隊 SQL 風格指南 (大小寫、縮排、別名命名)。
  • 使用格式化工具 (SQL Prompt, Poor Man's T-SQL Formatter)。
  • 複雜查詢拆解為 CTE,逐步驗證中間結果。

總結對照表

低效寫法推薦改寫核心理由
IN (subquery)EXISTS / JOIN避免子查詢具體化、利用索引巢狀迴圈
NOT INNOT EXISTS / LEFT JOIN ... IS NULLNULL 語意陷阱、無索引
col <> valcol > val OR col < val<> 永遠全掃
IS [NOT] NULL預設值 / 位圖索引 (僅 DW)B-tree 不存 NULL
LIKE '%abc%'LIKE 'abc%' / 全文檢索前置萬用字元殺索引
UNIONUNION ALL去重排序開銷

將上述模式內化為編碼肌肉記憶,配合定期 EXPLAIN PLAN / SQL Monitoring 驗證,即能持續產出高效能 Oracle SQL。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved