????????MySQL 和 Oracle 作為主流關系型數據庫,其索引失效的場景既有共性,也因底層優化器、索引類型支持等差異存在不同。以下從常見索引失效場景對比兩者的表現及原因:
一、索引列上使用函數 / 表達式
共性:若直接在索引列上使用函數或表達式(如
SUBSTR(name, 1, 3)
、age + 1
),優化器通常無法利用索引,導致失效。- 例:
WHERE SUBSTR(name, 1, 3) = 'abc'
(name
為索引列),兩者均可能失效。
- 例:
差異:
- MySQL:在 8.0 版本前不支持 “函數索引”,此類場景必然失效;8.0 后支持函數索引(需顯式創建,如
CREATE INDEX idx_func ON t (SUBSTR(name, 1, 3))
),創建后可避免失效。 - Oracle:原生支持 “函數索引”(如
CREATE INDEX idx_func ON t (SUBSTR(name, 1, 3))
),若查詢中的函數與索引定義一致,可正常使用索引,否則失效。
- MySQL:在 8.0 版本前不支持 “函數索引”,此類場景必然失效;8.0 后支持函數索引(需顯式創建,如
二、OR 連接的條件中存在無索引列
共性:若
OR
連接的多個條件中,存在某列未建索引,優化器可能放棄使用索引(因需同時掃描索引和非索引列,效率可能低于全表掃描)。差異:
- MySQL:對
OR
的處理較嚴格。即使OR
兩邊的列都有索引,也可能因優化器判斷成本較高而失效(尤其當索引選擇性低時)。例如:WHERE age = 20 OR name = 'abc'
(兩列均有索引),可能仍走全表掃描。 - Oracle:優化器對
OR
的兼容性更好。若OR
兩邊的列均有索引,通常會使用索引合并(Index Merge)策略,避免全表掃描。
- MySQL:對
三、否定操作符(!=、<>、NOT IN、IS NOT NULL)
共性:此類操作符可能導致索引失效,因優化器認為掃描范圍較大,全表掃描更高效。
差異:
- MySQL:
!=
、NOT IN
、IS NOT NULL
幾乎必然導致索引失效(僅當索引列值分布極不均勻時可能例外)。例如:WHERE age != 20
(age
有索引),通常走全表掃描。 - Oracle:處理更靈活。若索引列值稀疏(如大部分為
NULL
,查詢IS NOT NULL
),或NOT IN
的范圍極小,可能仍使用索引(但效率較低)。
- MySQL:
四、隱式類型轉換
- 共性:當索引列類型與查詢條件值類型不匹配時,數據庫會自動進行類型轉換(如字符串列
name
用數字123
查詢),導致索引失效。- 例:
WHERE name = 123
(name
為VARCHAR
類型),兩者均會失效(因轉換為WHERE CAST(name AS UNSIGNED) = 123
,等價于函數操作)。
- 例:
五、模糊查詢(LIKE)
共性:以
%
開頭的模糊查詢(如LIKE '%abc'
),索引通常失效(因無法通過索引前綴定位);以常量開頭的查詢(如LIKE 'abc%'
),可能使用索引。差異:
- MySQL:
LIKE 'abc%'
僅當索引列是字符串類型且無其他復雜條件時,才會使用索引;若結合其他條件(如AND age > 20
),可能失效。 - Oracle:
LIKE 'abc%'
對 B 樹索引的支持更穩定,即使結合其他簡單條件,也更可能使用索引(優化器對范圍掃描的判斷更靈活)。
- MySQL:
六、聯合索引違反 “最左前綴原則”
共性:聯合索引(如
(a, b, c)
)需滿足 “最左前綴”(查詢條件包含a
,或a + b
,或a + b + c
),否則失效。- 例:聯合索引
(a, b)
,查詢WHERE b = 10
,兩者均失效。
- 例:聯合索引
差異:
- MySQL:若聯合索引中左側列有 “范圍查詢”(如
a > 10
),則右側列的索引失效(如WHERE a > 10 AND b = 20
,僅a
的索引有效,b
失效)。 - Oracle:優化器可能對范圍查詢后的列進行 “跳躍掃描”(Index Skip Scan),尤其當左側列的基數(不同值數量)較小時(如
a
只有 2 個值),即使a
用范圍查詢,b
仍可能使用索引。
- MySQL:若聯合索引中左側列有 “范圍查詢”(如
七、數據量極小或索引選擇性低
共性:當表數據量極小(如 <1000 行),或索引列選擇性極低(如性別列,只有 “男 / 女”),優化器會認為全表掃描比索引掃描更快,主動忽略索引。
差異:
- MySQL:對 “小表” 的判斷更激進,即使表有幾萬行,若索引選擇性低(如重復值占比 > 50%),也可能放棄索引。
- Oracle:優化器對索引選擇性的判斷更精細,會結合統計信息(如直方圖)評估成本,選擇性略低時仍可能使用索引。
總結:核心差異點
場景 | MySQL 特點 | Oracle 特點 |
---|---|---|
函數索引支持 | 8.0 后支持,需顯式創建 | 原生支持,可直接適配查詢中的函數 |
OR 條件處理 | 嚴格,易失效,索引合并較少 | 靈活,索引合并較常見 |
否定操作符 | 幾乎必然失效 | 部分場景(如稀疏數據)可能使用索引 |
聯合索引范圍查詢 | 范圍后列索引失效 | 可能支持跳躍掃描,范圍后列仍可用索引 |
實際開發中,需結合數據庫類型、版本及執行計劃(EXPLAIN
/EXPLAIN PLAN
)判斷索引是否生效,避免依賴經驗主義。