MySQL索引不生效的8種原因與解決方法
在數(shù)據(jù)庫(kù)優(yōu)化中,最讓人頭疼的事情之一莫過(guò)于精心設(shè)計(jì)的索引沒有發(fā)揮作用。為什么會(huì)出現(xiàn)這種情況?

這篇文章帶大家一起探討一些常見原因,方便大家更好地理解MySQL查詢優(yōu)化器是如何選擇索引的,以及在出現(xiàn)類似問(wèn)題時(shí),可逐項(xiàng)進(jìn)行對(duì)照排查,
以一個(gè)簡(jiǎn)單的 people 表作為例子,表結(jié)構(gòu)如下:
CREATE TABLE `people` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `first_name` varchar(50) NOT NULL, `last_name` varchar(50) NOT NULL, `state` char(2) NOT NULL, PRIMARY KEY (`id`), KEY `first_name` (`first_name`), KEY `state` (`state`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
后續(xù)會(huì)以該表結(jié)構(gòu)為基礎(chǔ),通過(guò)添加或刪除索引來(lái)展示不同場(chǎng)景。
確認(rèn)索引是否被使用
在分析索引未生效的原因之前,首先需要判斷 MySQL 是否使用了索引??梢酝ㄟ^(guò) EXPLAIN 命令來(lái)查看查詢優(yōu)化器的分析結(jié)果,了解哪些索引被考慮,以及最終選擇使用了哪個(gè)索引。
例如,以下查詢會(huì)試圖通過(guò) first_name 索引查找數(shù)據(jù):
EXPLAIN SELECT * FROM people WHERE first_name = 'Aaron';
返回結(jié)果如下:
| id | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|
| 1 | people | ref | first_name | first_name | 202 | const | 180 | 100.00 |
從結(jié)果中可以看到:
possible_keys表示查詢優(yōu)化器會(huì)考慮的索引,這里是first_name索引。key表示實(shí)際被選中的索引,也是first_name。
關(guān)于EXPLAIN 的使用,可參考文末補(bǔ)充內(nèi)容
在本例中,first_name 索引不僅被優(yōu)化器考慮(considered),而且最終被選中(chosen)。這是兩個(gè)相關(guān)但不同的步驟:首先,優(yōu)化器會(huì)根據(jù)查詢篩選可用的索引;然后,選擇性能較優(yōu)的索引。
確認(rèn)索引是否被使用后,接下來(lái)分析一些索引未生效的常見原因。
索引未生效的原因
原因 1:另一個(gè)索引更優(yōu)
當(dāng)查詢可以利用多個(gè)索引時(shí),MySQL 優(yōu)化器會(huì)選擇其中最優(yōu)的索引。如果你的查詢可以同時(shí)使用多個(gè)索引,但最終未選擇預(yù)期的索引,很可能是因?yàn)榱硪粋€(gè)索引的效率更好。
例如,以下查詢同時(shí)使用 first_name 和 state 字段:
SELECT * FROM people WHERE first_name = 'Aaron' AND state = 'TX';
運(yùn)行 EXPLAIN 后結(jié)果如下:
| id | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
|---|---|---|---|---|---|---|---|---|---|
| 1 | people | ref | first_name,state | first_name | 202 | const | 180 | 50.00 | Using where |
在這個(gè)例子中,first_name 索引比 state 索引的選擇性更高,因此優(yōu)化器選擇了 first_name 索引。
原因 2:索引的選擇性和基數(shù)
索引的性能往往與選擇性和基數(shù)相關(guān):
- 基數(shù)(Cardinality) 是列中不同值的數(shù)量。
- 選擇性(Selectivity) 是指這些值的獨(dú)特程度(計(jì)算公式為
COUNT(DISTINCT column) / COUNT(*))。
比如,可以通過(guò)以下查詢計(jì)算基數(shù)和選擇性:
SELECT COUNT(DISTINCT first_name) as first_name_cardinality, COUNT(DISTINCT state) as state_cardinality, COUNT(DISTINCT first_name) / COUNT(*) as first_name_selectivity, COUNT(DISTINCT state) / COUNT(*) as state_selectivity FROM people;
結(jié)果如下:
| first_name_cardinality | state_cardinality | first_name_selectivity | state_selectivity |
|---|---|---|---|
| 3009 | 2 | 0.0060 | 0.0000 |
first_name字段的不同值非常多,因此選擇性較高。state列選擇性極低,導(dǎo)致通過(guò)state索引進(jìn)行過(guò)濾時(shí),效果較差。
高選擇性索引通常性能較優(yōu),而低選擇性索引在過(guò)濾數(shù)據(jù)時(shí)作用有限。
此外,唯一索引(如 id 的主鍵索引)通常具有完美選擇性。
原因 3:選擇性因查詢而異
索引的選擇性是基于整個(gè)表數(shù)據(jù)分布進(jìn)行計(jì)算的,但選擇性在具體查詢場(chǎng)景中可能不一樣。例如:
假如表中有 100 萬(wàn)行,其中 99% 的用戶類型是 user,只有 1% 為 admin,總體來(lái)看 type 列選擇性很低。但如果你的查詢條件是 type = 'admin',此時(shí)索引的作用就很明顯。
優(yōu)化器會(huì)根據(jù)查詢條件和數(shù)據(jù)分布動(dòng)態(tài)評(píng)估索引的價(jià)值。
原因 4:過(guò)時(shí)或不準(zhǔn)確的統(tǒng)計(jì)數(shù)據(jù)
MySQL 的索引基數(shù)統(tǒng)計(jì)信息是通過(guò)隨機(jī)采樣維護(hù)的,可能出現(xiàn)因統(tǒng)計(jì)信息過(guò)時(shí)而導(dǎo)致優(yōu)化器做出錯(cuò)誤決策的情況??梢酝ㄟ^(guò)以下命令更新統(tǒng)計(jì)信息:
ANALYZE TABLE people;
如果統(tǒng)計(jì)數(shù)據(jù)采樣精度不足,可以通過(guò)調(diào)整 MySQL 的相關(guān)參數(shù)改善采樣質(zhì)量。
原因 5:表掃描更快
某些情況下,優(yōu)化器會(huì)選擇直接掃描整個(gè)表而不是使用索引。這可能發(fā)生在以下場(chǎng)景:
- 表的大小較小,表掃描成本幾乎可以忽略。
- 查詢需要獲取大部分表數(shù)據(jù),索引的過(guò)濾能力不足,導(dǎo)致索引的額外開銷反而拖慢查詢速度。
雖然表掃描看起來(lái)反直覺,但在特定情況下確實(shí)更高效。
原因 6:索引的結(jié)構(gòu)性限制
理解索引的底層結(jié)構(gòu)(如 B+ 樹),有助于分析某些查詢?yōu)槭裁礋o(wú)法用到索引。主要有以下幾個(gè)場(chǎng)景:
場(chǎng)景 1:通配符搜索
MySQL 的索引只能用于匹配字符串的前綴部分,不能用于字符串中的后綴或包含部分。例如:
- 查詢
LIKE 'Aa%'可以使用索引。 - 查詢
LIKE '%ron'則無(wú)法使用索引。
如果你需要復(fù)雜的字符串搜索,可以考慮使用全文索引(Fulltext Index)或?qū)iT設(shè)計(jì)的數(shù)據(jù)模型。
場(chǎng)景 2:復(fù)合索引的左前綴規(guī)則
復(fù)合索引要求使用時(shí)遵循“左前綴”規(guī)則,例如:
ALTER TABLE people ADD INDEX multi (first_name, state);
- 查詢條件包含
first_name和state時(shí)會(huì)正確使用索引。 - 查詢條件僅包含
state時(shí)因不滿足左前綴無(wú)法使用復(fù)合索引。
場(chǎng)景 3:連接列類型或字符集不匹配
若連接的字段類型或字符集不一致,索引將無(wú)法生效。例如:
VARCHAR(10)和CHAR(10)類型和長(zhǎng)度相同,索引可用。VARCHAR(10)和CHAR(15)則因長(zhǎng)度不同導(dǎo)致索引不可用。
確保字段定義一致是索引生效的前提。
原因 7:索引被模糊化處理
某些查詢因?qū)ψ侄问褂昧撕瘮?shù)或運(yùn)算導(dǎo)致索引無(wú)法使用。例如:
SELECT * FROM people WHERE YEAR(created_at) = 2023;
上述查詢無(wú)法使用 created_at 索引,因?yàn)?MySQL 沒法直接基于函數(shù)計(jì)算進(jìn)行優(yōu)化。替代方案如下:
SELECT * FROM people WHERE created_at BETWEEN '2023-01-01' AND '2023-12-31';
通過(guò)范圍查詢可以正常使用索引。
原因 8:隱藏索引
MySQL 支持隱藏索引,隱藏索引不會(huì)被查詢優(yōu)化器使用。例如:
ALTER TABLE people ALTER INDEX first_name INVISIBLE;
Hidden 索引可以用于測(cè)試索引刪除的影響,若查詢性能下降可以隨時(shí)恢復(fù)索引。
強(qiáng)制使用索引
如果你認(rèn)為 MySQL 優(yōu)化器的決策不正確,可以通過(guò) USE INDEX 提示優(yōu)化器使用指定索引:
EXPLAIN SELECT * FROM people USE INDEX (state) WHERE first_name = 'Aaron' AND state = 'TX';
但使用 USE INDEX 應(yīng)該謹(jǐn)慎,因?yàn)榭赡茉跀?shù)據(jù)量增長(zhǎng)后需要重新評(píng)估是否強(qiáng)制使用某索引。
知識(shí)補(bǔ)充
僅僅會(huì)用MySQL的EXPLAIN還不夠,還需要會(huì)用EXPLAIN ANALYZE
在 MySQL 中,EXPLAIN 是一個(gè)關(guān)鍵字,用于了解查詢執(zhí)行的相關(guān)信息。本文將展示如何利用MySQL EXPLAIN 來(lái)解決查詢中的性能問(wèn)題。
雖然執(zhí)行一個(gè) EXPLAIN 計(jì)劃相對(duì)簡(jiǎn)單,但其輸出結(jié)果并不總是直觀的。只有了解其功能,才能充分利用它來(lái)實(shí)現(xiàn)SQL語(yǔ)句的性能提升。
EXPLAIN 與 EXPLAIN ANALYZE 的區(qū)別
當(dāng)在查詢的前面添加 EXPLAIN 關(guān)鍵字時(shí),它會(huì)解釋數(shù)據(jù)庫(kù)如何執(zhí)行該查詢以及估算的成本。
示例EXPLAIN語(yǔ)句:

通過(guò)利用這個(gè)MySQL 內(nèi)部工具,可以觀察到以下內(nèi)容:
- 查詢 ID:列中總包含一個(gè)數(shù)值,用于標(biāo)識(shí)該行屬于哪一個(gè) SELECT。
- SELECT_TYPE:運(yùn)行 SELECT 時(shí),MySQL 將 SELECT 查詢分為簡(jiǎn)單類型和復(fù)雜類型(主要),如下表所示:
- SIMPLE:查詢不包含子查詢或 UNION;
- PRIMARY(復(fù)雜類型):復(fù)雜類型分為三大類:簡(jiǎn)單子查詢、派生表(FROM 子句中的子查詢)、UNION;
- DELETE:如果EXPLAIN的是 DELETE,select_type 會(huì)顯示 DELETE;
- 查詢運(yùn)行的表 :顯示執(zhí)行計(jì)劃中每一步驟所涉及的表。
- 查詢?cè)L問(wèn)的分區(qū) :列出訪問(wèn)了哪些表分區(qū)(如果表已分區(qū))。
- 所使用的連接類型(如果有):請(qǐng)注意,即使查詢中不包含連接,這一列也會(huì)填充。
- MySQL 可以選擇的索引 :列出所有可能的候選索引。
- MySQL 實(shí)際使用的索引 :顯示查詢選擇的索引,并指定索引的使用長(zhǎng)度。
- MySQL 選擇的索引的長(zhǎng)度:當(dāng) MySQL 使用復(fù)合索引時(shí),length 列是唯一能確定復(fù)合索引中的使用了多少列的方法。
- 查詢?cè)L問(wèn)的行數(shù):在設(shè)計(jì)數(shù)據(jù)庫(kù)實(shí)例中的索引時(shí),需要注意 rows 列。該列顯示了 MySQL 為完成請(qǐng)求而訪問(wèn)的行數(shù),這在設(shè)計(jì)索引時(shí)非常實(shí)用。查詢?cè)L問(wèn)的行越少,查詢速度越快。
- 與索引進(jìn)行比較的列
- 按指定條件過(guò)濾的行的百分比:該列顯示了滿足表上某些條件(如 WHERE 子句或連接條件)的行的悲觀估算百分比。將 rows 列的值乘以該百分比,可以看到 MySQL 估計(jì)要與查詢計(jì)劃中先前的表連接的行數(shù)。
- 與查詢相關(guān)的任何額外信息
總之,通過(guò)使用 EXPLAIN,可以獲得查詢預(yù)期運(yùn)行的步驟列表。
什么是 EXPLAIN ANALYZE
在 MySQL 8.0.18 中,MySQL 引入了 EXPLAIN ANALYZE,一個(gè)在常規(guī) EXPLAIN 查詢計(jì)劃工具之上的新功能。除了列出查詢計(jì)劃和估算的成本,EXPLAIN ANALYZE 還打印了執(zhí)行計(jì)劃中各個(gè)迭代器的實(shí)際成本。
示例EXPLAIN ANALYZE語(yǔ)句:

注意事項(xiàng):EXPLAIN ANALYZE 實(shí)際上會(huì)運(yùn)行查詢,因此如果你不希望查詢?cè)趯?shí)時(shí)數(shù)據(jù)庫(kù)上運(yùn)行,請(qǐng)不要使用 EXPLAIN ANALYZE。
對(duì)于每個(gè)迭代器,EXPLAIN ANALYZE 提供以下信息:
- 估算的執(zhí)行成本(一些迭代器未被成本模型納入,因此在估算中未包含它們)
- 估算的返回行數(shù)
- 返回第一行所需的時(shí)間
- 執(zhí)行迭代器所花費(fèi)的時(shí)間(包括子迭代器但不包括父迭代器),單位:毫秒。當(dāng)有多個(gè)循環(huán)時(shí),該數(shù)據(jù)會(huì)顯示平均每個(gè)循環(huán)所需的時(shí)間。
- 迭代器返回的行數(shù)
- 循環(huán)的次數(shù)
MySQL EXPLAIN ANALYZE 的結(jié)果會(huì)顯示查詢運(yùn)行前規(guī)劃器的估算數(shù)據(jù)(如圖中黃色突出顯示部分)和查詢實(shí)際運(yùn)行后的數(shù)據(jù)(如綠色突出顯示部分)。
EXPLAIN ANALYZE 的格式
EXPLAIN ANALYZE 可用于 SELECT 語(yǔ)句、多表 UPDATE 語(yǔ)句、DELETE 語(yǔ)句和 TABLE 語(yǔ)句。它會(huì)自動(dòng)選擇 FORMAT=tree 并執(zhí)行查詢(不會(huì)向用戶顯示任何輸出)。EXPLAIN ANALYZE 專注于查詢執(zhí)行的關(guān)系以及部分查詢的執(zhí)行順序。
EXPLAIN 輸出以節(jié)點(diǎn)形式組織。在最低層,節(jié)點(diǎn)會(huì)掃描表或搜索索引;較高層的節(jié)點(diǎn)則操作來(lái)自低層節(jié)點(diǎn)的結(jié)果。
雖然 MySQL CLI 能以表格、制表符、垂直格式,以及漂亮或原始 JSON 格式打印 EXPLAIN 結(jié)果,但目前 EXPLAIN ANALYZE 不支持 JSON 格式。
EXPLAIN 和EXPLAIN ANALYZE的使用場(chǎng)景
當(dāng)你不確定查詢是否高效運(yùn)行時(shí),可以(且應(yīng))使用 EXPLAIN 查詢。如果你認(rèn)為已經(jīng)正確索引并分區(qū)了表,但查詢依舊運(yùn)行緩慢,則可能需要使用EXPLAIN ANALYZE了。當(dāng)查詢進(jìn)行EXPLAIN ANALYZE之后,就需要關(guān)注的輸出內(nèi)容以及優(yōu)化目標(biāo)了。
1.索引相關(guān)列:keys、possible keys 和 key lengths
在 MySQL 中處理索引時(shí),需關(guān)注 possible_keys、key 和 key_len 列。
- possible_keys 列顯示了 MySQL 可以選擇的索引。
- key 列顯示了實(shí)際選擇的索引。
- key_len 列顯示了所選索引的長(zhǎng)度。
這些信息對(duì)設(shè)計(jì)索引、為特定任務(wù)決定使用何種索引,以及處理相關(guān)問(wèn)題(如選擇覆蓋索引的適當(dāng)長(zhǎng)度)非常實(shí)用。
2.FULLTEXT 索引與連接
當(dāng)使用 FULLTEXT 索引確保查詢參與 JOIN 操作時(shí),需注意 select_type 列,該列的值應(yīng)為 fulltext。
3.分區(qū)
如果表已添加分區(qū)并希望查詢使用這些分區(qū),要觀察 partition 列。如果 MySQL 實(shí)例正在使用分區(qū),在大多數(shù)情況下,MySQL 會(huì)自動(dòng)處理所有查詢,而無(wú)需額外操作。如果希望查詢使用特定分區(qū),可以使用類似 SELECT * FROM TABLE_NAME PARTITION(p1,p2) 的查詢。
EXPLAIN 的局限性
EXPLAIN 是一種估算工具。它有時(shí)是一個(gè)比較準(zhǔn)確的估算,但有時(shí)可能非常不精確。以下是一些局限性:
- EXPLAIN 不會(huì)告訴你觸發(fā)器、存儲(chǔ)函數(shù)或 UDF 對(duì)查詢的影響。
- 它不能分析存儲(chǔ)過(guò)程。
- 它不會(huì)展示 MySQL 在查詢執(zhí)行期間的優(yōu)化過(guò)程。
- 一些統(tǒng)計(jì)數(shù)據(jù)是估算值,可能非常不準(zhǔn)確。
- 它不會(huì)區(qū)分某些具有相同名稱的內(nèi)容。例如,它用
filesort表示內(nèi)存排序和磁盤排序,用Using temporary表示內(nèi)存臨時(shí)表和磁盤臨時(shí)表。
SHOW WARNINGS 語(yǔ)句
需要注意的一點(diǎn)是:如果你用 EXPLAIN 的查詢未正確解析,可以輸入 SHOW WARNINGS; 查看最后一個(gè)運(yùn)行的非診斷語(yǔ)句的信息。雖然它無(wú)法提供像 EXPLAIN 那樣的查詢執(zhí)行計(jì)劃,但它可能提供關(guān)于可處理的查詢片段的線索。
SHOW WARNINGS; 包含一些特殊標(biāo)記,其中信息可能包括:
<index_lookup>(query fragment):表明如果查詢正確解析會(huì)進(jìn)行索引查找。<if>(condition, expr1, expr2):表明該查詢特定部分有 IF 條件。<primary_index_lookup>(query fragment):表明通過(guò)主鍵進(jìn)行索引查找。<temporary table>:表明這里會(huì)創(chuàng)建內(nèi)部表以保存臨時(shí)結(jié)果(例如在連接之前的子查詢中)。
MySQL EXPLAIN 的連接類型
MySQL 手冊(cè)提到 type 列顯示“連接類型”,用以解釋表的連接方式。但實(shí)際上更準(zhǔn)確的說(shuō)法是“訪問(wèn)類型”,即告訴我們 MySQL 決定如何在表中找到行。
以下列出從性能最佳到最差的重要訪問(wèn)方式:
- NULL(較好):表示 MySQL 在優(yōu)化階段即可解析查詢,不會(huì)在執(zhí)行階段訪問(wèn)表或索引。
- system(較好):表為空或僅有一行記錄。
- const(較好):列值可視為常量(即查詢只匹配一行)。注:主鍵查找、唯一索引查找。
- eq_ref(較好):索引是聚簇索引,被 操作使用(索引為主鍵或 NOT NULL 的唯一索引)。
- ref(較好):使用等值運(yùn)算符訪問(wèn)索引列。注:
ref_or_null是ref的變種,表示初次查找后需再查找 NULL 條目。 - fulltext(一般):操作(JOIN)使用了表的 FULLTEXT 索引。
- index(一般):掃描整個(gè)索引以找到查詢匹配項(xiàng)。注:主要優(yōu)勢(shì)是無(wú)需排序;主要劣勢(shì)是讀取整張表成本高。
- range(一般):范圍掃描為受限索引掃描,從索引某點(diǎn)開始返回匹配范圍內(nèi)的記錄。注:這比全索引掃描更優(yōu)。
- all(一般):MySQL 為滿足查詢而掃描全表。
還有一些其他類型需要了解:
- index_merge:此連接類型表示使用了索引合并優(yōu)化,即通過(guò)多索引聯(lián)合查詢單表。
- unique_subquery:此類型替代某些形式的
eq_ref。通常用于以下形式的子查詢:value IN (SELECT primary_key FROM single_table WHERE some_expr)。 - index_subquery:與
unique_subquery類似,但應(yīng)用于非唯一索引的子查詢。
EXPLAIN 的 EXTRA 列
EXTRA 列包含其他列中未涵蓋的額外信息。以下是一些重要值及其定義:
- Using index:表示 MySQL 將使用覆蓋索引避免訪問(wèn)表。
- Using where:MySQL 服務(wù)器將在存儲(chǔ)引擎檢索行后進(jìn)行行的后過(guò)濾。
- Using temporary:MySQL 會(huì)通過(guò)臨時(shí)表保存排序結(jié)果。
- Using filesort:MySQL 使用外部排序來(lái)排序結(jié)果而非按照索引順序讀取行。
- Range checked for each record:(index map:N),表示沒有合適索引,并會(huì)對(duì)連接中的每行重新評(píng)估索引。
- Using index condition:表通過(guò)訪問(wèn)索引元組并在讀取完整表之前進(jìn)行測(cè)試讀取。
- Backward index scan:MySQL 使用降序索引完成查詢。
- const row not found:表明查詢的表為空。
- Using index for group-by:表明 MySQL 能利用某個(gè)索引優(yōu)化 GROUP BY 操作。
EXPLAIN 優(yōu)化查詢的實(shí)踐示例
下面通過(guò)一個(gè)實(shí)踐案例來(lái)演示一下使用 MySQL EXPLAIN 優(yōu)化查詢的方法。
1.運(yùn)行初始查詢
在開始之前,先創(chuàng)建一個(gè)數(shù)據(jù)庫(kù),并使用MySQL員工樣例數(shù)據(jù)庫(kù)進(jìn)行初始化。
通過(guò)使用多列索引和MySQL EXPLAIN,允許數(shù)據(jù)庫(kù)引擎聯(lián)合使用多列加速查詢。
例如,優(yōu)化下列查詢:
SELECT * FROM employees WHERE last_name = 'Puppo' AND first_name = 'Kendra';

在運(yùn)行該查詢后,EXPLAIN 的結(jié)果顯示訪問(wèn)了 299,733 行,而這是我們需要優(yōu)化以提升性能的根本原因。
優(yōu)化方法 1:創(chuàng)建兩個(gè)獨(dú)立索引
一種方法是分別為 last_name 列和 first_name 列創(chuàng)建單獨(dú)索引,但這種方式有一個(gè)問(wèn)題——MySQL 知道如何找到所有姓 Puppo 的員工,也知道如何找到所有名為 Kendra 的員工,但卻無(wú)法同時(shí)高效找到名為 Kendra Puppo 的員工。
其他需要注意的事項(xiàng):
- 當(dāng)面對(duì)多個(gè)不相關(guān)的索引以及包含多個(gè)過(guò)濾條件的查詢時(shí),MySQL 有幾種選擇可以用來(lái)處理這些情況。
- MySQL 支持索引合并優(yōu)化(Index Merge),可聯(lián)合使用多個(gè)索引來(lái)執(zhí)行查詢。然而,這種優(yōu)化有一定局限性,因此在構(gòu)建索引時(shí)應(yīng)該將其視為一般規(guī)則。MySQL 可能會(huì)決定不使用多個(gè)索引;即使會(huì)使用,在很多情況下,多個(gè)索引的聯(lián)合效果也遠(yuǎn)遠(yuǎn)不如一個(gè)專門的索引。
優(yōu)化方法 2:使用多列索引
由于第一種方法的問(wèn)題,我們知道需要找到一種解決方案來(lái)使用能夠考慮多列的索引。這里我們可以使用多列索引來(lái)實(shí)現(xiàn)這一目標(biāo)。
可以將其想象成一本電話簿嵌套在另一本電話簿中。首先,查閱姓氏 “Puppo”,然后進(jìn)入第二個(gè)目錄,該目錄按名字的字母順序組織所有名為 “Kendra” 的人,在這個(gè)目錄中可以快速找到“Kendra Puppo”。
在 MySQL 中,若要為 employees 表中的姓氏和名字創(chuàng)建多列索引,可以執(zhí)行以下命令:
CREATE INDEX fullnames ON employees(last_name, first_name);
現(xiàn)在,多列索引已成功創(chuàng)建,我們可以執(zhí)行以下 SELECT 查詢來(lái)查找名字為 Kendra 且姓氏為 Puppo 的記錄。結(jié)果將是一行數(shù)據(jù),其中包含名為 Kendra Puppo 的員工信息。
使用 EXPLAIN 來(lái)檢查該查詢是否使用了索引:

查詢優(yōu)化后的結(jié)果顯示,索引被使用,并且只訪問(wèn)了一行數(shù)據(jù)來(lái)完成請(qǐng)求。這比優(yōu)化前必須訪問(wèn) 299,733 行要高效得多。
總結(jié)
索引優(yōu)化涉及多個(gè)方面,包括查詢優(yōu)化器運(yùn)作、數(shù)據(jù)分布、索引結(jié)構(gòu)等。了解索引未生效的原因并合理優(yōu)化查詢,可以顯著提升數(shù)據(jù)庫(kù)性能。索引雖強(qiáng)大,但只有正確規(guī)劃和使用才能發(fā)揮最大效用。
到此這篇關(guān)于MySQL索引不生效的8種原因與解決方法的文章就介紹到這了,更多相關(guān)MySQL索引不生效內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL實(shí)戰(zhàn)記錄之如何快速定位慢SQL
這可能是困然很多人的一個(gè)問(wèn)題,MySQL通過(guò)慢查詢?nèi)罩径ㄎ荒切﹫?zhí)行效率較低的SQL語(yǔ)句,下面這篇文章主要給大家介紹了關(guān)于MySQL實(shí)戰(zhàn)記錄之如何快速定位慢SQL的相關(guān)資料,需要的朋友可以參考下2022-03-03
mysql動(dòng)態(tài)游標(biāo)學(xué)習(xí)(mysql存儲(chǔ)過(guò)程游標(biāo))
mysql動(dòng)態(tài)游標(biāo)示例,通過(guò)準(zhǔn)備語(yǔ)句、視圖和靜態(tài)游標(biāo)實(shí)現(xiàn),大家參考使用吧2013-12-12
云服務(wù)器Ubuntu_Server_16.04.1安裝MySQL并開啟遠(yuǎn)程連接的方法
這篇文章主要介紹了云服務(wù)器Ubuntu_Server_16.04.1安裝MySQL并開啟遠(yuǎn)程連接的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2018-02-02
MySQL 用戶管理和數(shù)據(jù)庫(kù)權(quán)限問(wèn)題
MySQL作為世界上最流行的開源關(guān)系型數(shù)據(jù)庫(kù),在實(shí)際生產(chǎn)環(huán)境中,合理的用戶管理和權(quán)限控制是確保數(shù)據(jù)安全的重要基石,本文將從零開始,手把手教你掌握MySQL的用戶管理和權(quán)限控制,感興趣的朋友一起看看吧2025-06-06

