MySQL中OR條件查詢引發(fā)索引失效的場景及解決方案
今天這篇文章我們來簡單介紹一下MySQL的OR條件查詢,以及它可能會(huì)引發(fā)的索引失效(即不走索引)的場景以及解決方案。方便大家在實(shí)踐中,留意是否正確使用了OR條件查詢。
MySQL的OR條件查詢簡介
在 MySQL 中,OR 條件查詢是一種利用 OR 邏輯操作符在 WHERE 子句中連接多個(gè)條件的查詢方式。當(dāng)查詢中使用 OR 操作符時(shí),只要其中任何一個(gè)條件滿足就會(huì)返回對應(yīng)的數(shù)據(jù)行。它是一種常見的邏輯運(yùn)算,用于實(shí)現(xiàn)靈活的數(shù)據(jù)篩選。
OR條件查詢經(jīng)常用于:多字段查詢、聯(lián)合范圍查詢、動(dòng)態(tài)篩選等場景。
多字段查詢示例:
SELECT * FROM users WHERE name = 'Alice' OR city = 'Chicago';
聯(lián)合范圍查詢示例:
SELECT * FROM users WHERE age < 30 OR age > 35;
動(dòng)態(tài)篩選示例:
SELECT * FROM orders WHERE status = 'pending' OR status = 'processing';
其中,在多字段查詢的場景下,需要特別留意是否會(huì)出現(xiàn)不走索引的情況,下面我們來詳細(xì)介紹一下這種情況及解決方案。
不走索引案例分析
如果查詢條件中包含 OR 操作符,通常情況下,即使其中一個(gè)條件是基于索引的,MySQL 也可能不會(huì)使用該索引,轉(zhuǎn)而執(zhí)行全表掃描(Table Scan)。
原因:MySQL 查詢優(yōu)化器無法高效地利用索引來處理 OR 條件,尤其是在多個(gè)條件中一個(gè)或多個(gè)字段沒有索引的情況下。
推薦操作:盡量避免使用 OR,可以通過 UNION ALL 或 UNION 來重構(gòu)查詢邏輯,從而強(qiáng)制使用索引。
案例分析
假設(shè)有一個(gè)表 example_table,結(jié)構(gòu)如下:
CREATE TABLE example_table (
id INT NOT NULL, -- 有索引字段
name VARCHAR(100), -- 沒有索引字段
age INT, -- 有索引字段
PRIMARY KEY (id), -- 主鍵索引
INDEX index_age (age) -- 輔助索引
);
插入一些測試數(shù)據(jù):
INSERT INTO example_table (id, name, age) VALUES (1, 'Alice', 30), (2, 'Bob', 25), (3, 'Charlie', 35), (4, 'Dave', 40);
使用OR條件的查詢:
mysql> EXPLAIN SELECT * FROM example_table WHERE id = 1 OR name = 'Alice' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: example_table
partitions: NULL
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 4
filtered: 43.75
Extra: Using where
分析:
id = 1是主鍵查詢,本應(yīng)該使用索引PRIMARY。- 但是,由于包含
OR條件name = 'Alice',而name列沒有索引,MySQL 的優(yōu)化器選擇了不使用索引而執(zhí)行全表掃描。 - 最終結(jié)果:查詢執(zhí)行了全表掃描 (
type: ALL)。
解決方案
方法 1:使用UNION替代OR
將原查詢拆分,并通過 UNION 分別處理有索引和無索引的條件,從而強(qiáng)制使用索引:
mysql> EXPLAIN SELECT * FROM example_table WHERE id = 1
-> UNION ALL
-> SELECT * FROM example_table WHERE name = 'Alice' \G
*************************** 1. row ***************************
id: 1
select_type: PRIMARY
table: example_table
partitions: NULL
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: NULL
*************************** 2. row ***************************
id: 2
select_type: UNION
table: example_table
partitions: NULL
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 4
filtered: 25.00
Extra: Using where
通過執(zhí)行計(jì)劃可以看出,對于第一部分查詢使用了索引,對于第二部分查詢使用全表掃描,因?yàn)?code>name字段無索引。雖然仍有一部分未使用索引,但數(shù)據(jù)量較大的情況下,這種分拆方式對性能更優(yōu)。
方法 2:添加索引優(yōu)化
如果查詢中經(jīng)常根據(jù) name 條件篩選數(shù)據(jù),可以考慮為 name 列添加索引:
mysql> ALTER TABLE example_table ADD INDEX index_name (name);
?
mysql> explain SELECT * FROM example_table WHERE id = 1 OR name = 'Alice' \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: example_table
partitions: NULL
type: index_merge
possible_keys: PRIMARY,index_name
key: PRIMARY,index_name
key_len: 4,403
ref: NULL
rows: 2
filtered: 100.00
Extra: Using union(PRIMARY,index_name); Using where
針對name列添加索引之后,MySQL 使用了 index_merge 查詢優(yōu)化策略,結(jié)合主鍵索引和輔助索引 index_name。數(shù)據(jù)量較大的時(shí)候,這種方式可以顯著加速查詢,避免全表掃描。
總結(jié)規(guī)則
第一、一般規(guī)則:
- 查詢條件使用
OR且部分字段沒有索引時(shí),MySQL 很可能會(huì)選擇執(zhí)行全表掃描,而不是使用索引。 - MySQL 的查詢優(yōu)化器在處理
OR時(shí)效率較差。
第二、優(yōu)化建議:
- 盡量避免使用
OR,使用UNION ALL或UNION替代。 - 根據(jù)查詢條件頻率,合理為字段創(chuàng)建索引。
- 如果數(shù)據(jù)復(fù)雜,可以通過改寫查詢邏輯,分拆條件使得索引能被充分使用。
第三、特別注意:
OR 可能導(dǎo)致索引失效的情況對于大數(shù)據(jù)量的表尤為關(guān)鍵,因?yàn)槿頀呙璧男阅艽鷥r(jià)在數(shù)據(jù)量增加時(shí)會(huì)嚴(yán)重影響查詢速度。
到此這篇關(guān)于MySQL中OR條件查詢引發(fā)索引失效的場景及解決方案的文章就介紹到這了,更多相關(guān)MySQL OR條件查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
explain執(zhí)行計(jì)劃需要關(guān)注的幾個(gè)關(guān)鍵字段詳細(xì)解釋
這篇文章主要介紹了explain執(zhí)行計(jì)劃需要關(guān)注的幾個(gè)關(guān)鍵字段的相關(guān)資料,EXPLAIN是MySQL性能優(yōu)化的關(guān)鍵工具,它提供了查詢執(zhí)行計(jì)劃的詳細(xì)信息,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-02-02
設(shè)置MySQL中的數(shù)據(jù)類型來優(yōu)化運(yùn)行速度的實(shí)例
這篇文章主要介紹了設(shè)置MySQL中索引的數(shù)據(jù)類型來優(yōu)化運(yùn)行速度的實(shí)例,主要是適當(dāng)使用短字節(jié)的數(shù)據(jù)類型來處理短索引,需要的朋友可以參考下2015-05-05
mysql5.5 master-slave(Replication)配置方法
mysql5.5 master-slave(Replication)配置方法,需要的朋友可以參考下。2011-08-08
MySql中having字句對組記錄進(jìn)行篩選使用說明
having字句可以讓我們篩選成組后的各種數(shù)據(jù)2012-12-12
詳談innodb的鎖(record,gap,Next-Key lock)
下面小編就為大家?guī)硪黄斦刬nnodb的鎖(record,gap,Next-Key lock)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03
mysql installer community 8.0.12.0安裝圖文教程
這篇文章主要為大家詳細(xì)介紹了mysql installer community 8.0.12.0安裝圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08

