mysql中添加索引的3種方法及使用注意事項(xiàng)詳解
一、MySQL 創(chuàng)建索引的三種方法
1.1 在新建表時(shí)創(chuàng)建索引
-- ① 普通索引
CREATE TABLE t_dept (
no INT NOT NULL PRIMARY KEY,
name VARCHAR(20) NULL,
sex VARCHAR(2) NULL,
info VARCHAR(20) NULL,
INDEX index_no(no)
);
-- ② 唯一索引
CREATE TABLE t_dept (
no INT NOT NULL PRIMARY KEY,
name VARCHAR(20) NULL,
sex VARCHAR(2) NULL,
info VARCHAR(20) NULL,
UNIQUE INDEX index_name(name)
);
-- ③ 全文索引(全文索引字段通常為 TEXT 或 VARCHAR,且 InnoDB 在 MySQL 5.6+ 才支持全文索引,早期版本僅 MyISAM 支持。)
CREATE TABLE t_dept (
no INT NOT NULL PRIMARY KEY,
name VARCHAR(20) NULL,
sex VARCHAR(2) NULL,
info TEXT NULL, -- 全文索引字段建議用 TEXT
FULLTEXT INDEX index_info(info)
);
-- ④ 多列(復(fù)合)索引
CREATE TABLE t_dept (
no INT NOT NULL PRIMARY KEY,
name VARCHAR(20) NULL,
sex VARCHAR(2) NULL,
info VARCHAR(20) NULL,
INDEX idx_no_name(no, name)
);
1.2 在已存在表上通過CREATE INDEX添加索引
-- 普通索引 CREATE INDEX idx_name ON t_dept(name); -- 唯一索引 CREATE UNIQUE INDEX idx_name ON t_dept(name); -- 全文索引 CREATE FULLTEXT INDEX idx_info ON t_dept(info); -- 多列索引 CREATE INDEX idx_name_no ON t_dept(name, no);
?? 此方式不能用于主鍵或外鍵約束,僅用于普通/唯一/全文索引。
1.3 通過ALTER TABLE修改表結(jié)構(gòu)添加索引
-- 普通索引 ALTER TABLE t_dept ADD INDEX idx_name(name); -- 唯一索引 ALTER TABLE t_dept ADD UNIQUE INDEX idx_name(name); -- 全文索引 ALTER TABLE t_dept ADD FULLTEXT INDEX idx_info(info); -- 多列索引 ALTER TABLE t_dept ADD INDEX idx_name_no(name, no);
? 推薦在生產(chǎn)環(huán)境中使用
ALTER TABLE,語(yǔ)義更清晰,且支持更多選項(xiàng)(如指定索引類型)。
二、MySQL 索引類型與適用場(chǎng)景
| 索引類型 | 關(guān)鍵字 | 特點(diǎn) | 適用場(chǎng)景 |
|---|---|---|---|
| 普通索引 | INDEX / KEY | 加速查詢,允許重復(fù)值 | 高頻 WHERE、ORDER BY 字段 |
| 唯一索引 | UNIQUE | 值唯一,自動(dòng)校驗(yàn)重復(fù) | 身份證號(hào)、郵箱、訂單號(hào)等需唯一字段 |
| 主鍵索引 | PRIMARY KEY | 特殊的唯一索引,一張表僅一個(gè) | 表的主標(biāo)識(shí)(自增 ID 等) |
| 全文索引 | FULLTEXT | 支持關(guān)鍵詞全文檢索 | 文章內(nèi)容、商品描述等大文本字段 |
| 復(fù)合索引 | INDEX(col1, col2, ...) | 多字段組合索引 | 多條件聯(lián)合查詢(注意最左前綴原則) |
三、索引使用注意事項(xiàng)與限制
有效使用索引的場(chǎng)景
WHERE column = ?WHERE column LIKE 'abc%'(前綴匹配)ORDER BY column(無(wú)表達(dá)式)- 復(fù)合索引遵循 最左前綴原則:
INDEX(A,B,C)可用于(A)、(A,B)、(A,B,C)查詢
索引失效的常見情況
| 場(chǎng)景 | 示例 | 是否走索引 |
|---|---|---|
| 使用函數(shù) | WHERE DAY(create_time) = '2024-01-01' | ? |
| 不等號(hào)查詢 | WHERE status != 1 | ?(部分情況可能走) |
| 通配符開頭 | WHERE name LIKE '%john' | ? |
| 類型隱式轉(zhuǎn)換 | WHERE user_id = '123'(user_id 為 INT) | ? |
| OR 條件未全覆蓋索引 | WHERE name = 'a' OR age = 20(僅 name 有索引) | ? |
四、索引的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 顯著提升 SELECT 查詢速度
- 加速 JOIN、ORDER BY、GROUP BY 操作
- 唯一索引保障數(shù)據(jù) 完整性
缺點(diǎn)
- 降低寫性能:INSERT/UPDATE/DELETE 需同步更新索引
- 占用磁盤空間:索引文件可能接近甚至超過數(shù)據(jù)本身
- 維護(hù)成本高:過多索引增加優(yōu)化器負(fù)擔(dān)
?? 建議:
- 單表索引數(shù)量 ≤ 5~8 個(gè)(MySQL 限制最多 16 個(gè))
- 僅為 高頻查詢字段 建索引
- 避免為低區(qū)分度字段建索引(如性別、狀態(tài) 0/1)
五、InnoDB 與 MyISAM 索引差異
| 特性 | InnoDB | MyISAM |
|---|---|---|
| 主鍵索引 | 聚簇索引(數(shù)據(jù)按主鍵物理存儲(chǔ)) | 非聚簇索引 |
| 全文索引 | MySQL 5.6+ 支持 | 原生支持 |
| 行級(jí)鎖 | 基于索引實(shí)現(xiàn) | 不支持行鎖 |
| 崩潰恢復(fù) | 支持事務(wù)回滾 | 無(wú)事務(wù) |
?? 關(guān)鍵點(diǎn):InnoDB 的行鎖是通過索引實(shí)現(xiàn)的!無(wú)索引的 UPDATE 會(huì)鎖全表。
六、索引優(yōu)化工具:EXPLAIN
使用 EXPLAIN 分析 SQL 執(zhí)行計(jì)劃:
EXPLAIN SELECT * FROM t_dept WHERE name = 'IT';
重點(diǎn)關(guān)注字段:
type:訪問類型(const>ref>range>index>ALL)key:實(shí)際使用的索引rows:掃描行數(shù)(越小越好)Extra:是否出現(xiàn)Using filesort/Using temporary
七、總結(jié)
索引是一種特殊的文件(InnoDB數(shù)據(jù)表上的索引是表空間的一個(gè)組成部分),它們包含著對(duì)數(shù)據(jù)表里所有記錄的引用指針。
注:
[1]索引不是萬(wàn)能的!索引可以加快數(shù)據(jù)檢索操作,但會(huì)使數(shù)據(jù)修改操作變慢。每修改數(shù)據(jù)記錄,索引就必須刷新一次。為了在某種程序上彌補(bǔ)這一缺陷,許 多SQL命令都有一個(gè)DELAY_KEY_WRITE項(xiàng)。這個(gè)選項(xiàng)的作用是暫時(shí)制止MySQL在該命令每插入一條新記錄和每修改一條現(xiàn)有之后立刻對(duì)索引進(jìn) 行刷新,對(duì)索引的刷新將等到全部記錄插入/修改完畢之后再進(jìn)行。在需要把許多新記錄插入某個(gè)數(shù)據(jù)表的場(chǎng)合,DELAY_KEY_WRITE選項(xiàng)的作用將非 常明顯。
[2]另外,索引還會(huì)在硬盤上占用相當(dāng)大的空間。因此應(yīng)該只為最經(jīng)常查詢和最經(jīng)常排序的數(shù)據(jù)列建立索引。注意,如果某個(gè)數(shù)據(jù)列包含許多重復(fù)的內(nèi) 容,為它建立索引就沒有太大的實(shí)際效果。
從理論上講,完全可以為數(shù)據(jù)表里的每個(gè)字段分別建一個(gè)索引,但MySQL把同一個(gè)數(shù)據(jù)表里的索引總數(shù)限制為16個(gè)。
1. InnoDB數(shù)據(jù)表的索引
與MyISAM數(shù)據(jù)表相比,索引對(duì)InnoDB數(shù)據(jù)的重要性要大得多。在InnoDB數(shù)據(jù)表上,索引對(duì)InnoDB數(shù)據(jù)表的重要性要在得多。在 InnoDB數(shù)據(jù)表上,索引不僅會(huì)在搜索數(shù)據(jù)記錄時(shí)發(fā)揮作用,還是數(shù)據(jù)行級(jí)鎖定機(jī)制的基礎(chǔ)。”數(shù)據(jù)行級(jí)鎖定”的意思是指在事務(wù)操作的執(zhí)行過程中鎖定正 在被處理的個(gè)別記錄,不讓其他用戶進(jìn)行訪問。這種鎖定將影響到(但不限于)SELECT…LOCK IN SHARE MODE、SELECT…FOR UPDATE命令以及INSERT、UPDATE和DELETE命令。
出于效率方面的考慮,InnoDB數(shù)據(jù)表的數(shù)據(jù)行級(jí)鎖定實(shí)際發(fā)生在它們的索引上,而不是數(shù)據(jù)表自身上。顯然,數(shù)據(jù)行級(jí)鎖定機(jī)制只有在有關(guān)的數(shù)據(jù)表有一個(gè)合 適的索引可供鎖定的時(shí)候才能發(fā)揮效力。
2. 限制
如果WEHERE子句的查詢條件里有不等號(hào)(WHERE coloum != …),MySQL將無(wú)法使用索引。
類似地,如果WHERE子句的查詢條件里使用了函數(shù)(WHERE DAY(column) = …),MySQL也將無(wú)法使用索引。
在JOIN操作中(需要從多個(gè)數(shù)據(jù)表提取數(shù)據(jù)時(shí)),MySQL只有在主鍵和外鍵的數(shù)據(jù)類型相同時(shí)才能使用索引。
如果WHERE子句的查詢條件里使用比較操作符LIKE和REGEXP,MySQL只有在搜索模板的第一個(gè)字符不是通配符的情況下才能使用索引。比如說, 如果查詢條件是LIKE ‘abc%’,MySQL將使用索引;如果查詢條件是LIKE ‘%abc’,MySQL將不使用索引。
在ORDER BY操作中,MySQL只有在排序條件不是一個(gè)查詢條件表達(dá)式的情況下才使用索引。(雖然如此,在涉及多個(gè)數(shù)據(jù)表查詢里,即使有索引可用,那些索引在加快 ORDER BY方面也沒什么作用)
如果某個(gè)數(shù)據(jù)列里包含許多重復(fù)的值,就算為它建立了索引也不會(huì)有很好的效果。比如說,如果某個(gè)數(shù)據(jù)列里包含的凈是些諸如”0/1″或”Y/N”等值,就沒 有必要為它創(chuàng)建一個(gè)索引。
普通索引、唯一索引和主索引
1. 普通索引
普通索引(由關(guān)鍵字KEY或INDEX定義的索引)的唯一任務(wù)是加快對(duì)數(shù)據(jù)的訪問速度。因此,應(yīng)該只為那些最經(jīng)常出現(xiàn)在查詢條件(WHERE column = …)或排序條件(ORDER BY column)中的數(shù)據(jù)列創(chuàng)建索引。只要有可能,就應(yīng)該選擇一個(gè)數(shù)據(jù)最整齊、最緊湊的數(shù)據(jù)列(如一個(gè)整數(shù)類型的數(shù)據(jù)列)來(lái)創(chuàng)建索引。
2. 唯一索引
普通索引允許被索引的數(shù)據(jù)列包含重復(fù)的值。比如說,因?yàn)槿擞锌赡芡?,所以同一個(gè)姓名在同一個(gè)”員工個(gè)人資料”數(shù)據(jù)表里可能出現(xiàn)兩次或更多次。
如果能確定某個(gè)數(shù)據(jù)列將只包含彼此各不相同的值,在為這個(gè)數(shù)據(jù)列創(chuàng)建索引的時(shí)候就應(yīng)該用關(guān)鍵字UNIQUE把它定義為一個(gè)唯一索引。這么做的好處:一是簡(jiǎn) 化了MySQL對(duì)這個(gè)索引的管理工作,這個(gè)索引也因此而變得更有效率;二是MySQL會(huì)在有新記錄插入數(shù)據(jù)表時(shí),自動(dòng)檢查新記錄的這個(gè)字段的值是否已經(jīng)在 某個(gè)記錄的這個(gè)字段里出現(xiàn)過了;如果是,MySQL將拒絕插入那條新記錄。也就是說,唯一索引可以保證數(shù)據(jù)記錄的唯一性。事實(shí)上,在許多場(chǎng)合,人們創(chuàng)建唯 一索引的目的往往不是為了提高訪問速度,而只是為了避免數(shù)據(jù)出現(xiàn)重復(fù)。
3. 主索引
在前面已經(jīng)反復(fù)多次強(qiáng)調(diào)過:必須為主鍵字段創(chuàng)建一個(gè)索引,這個(gè)索引就是所謂的”主索引”。主索引與唯一索引的唯一區(qū)別是:前者在定義時(shí)使用的關(guān)鍵字是 PRIMARY而不是UNIQUE。
4. 外鍵索引
如果為某個(gè)外鍵字段定義了一個(gè)外鍵約束條件,MySQL就會(huì)定義一個(gè)內(nèi)部索引來(lái)幫助自己以最有效率的方式去管理和使用外鍵約束條件。
5. 復(fù)合索引
索引可以覆蓋多個(gè)數(shù)據(jù)列,如像INDEX(columnA, columnB)索引。這種索引的特點(diǎn)是MySQL可以有選擇地使用一個(gè)這樣的索引。如果查詢操作只需要用到columnA數(shù)據(jù)列上的一個(gè)索引,就可以使 用復(fù)合索引INDEX(columnA, columnB)。不過,這種用法僅適用于在復(fù)合索引中排列在前的數(shù)據(jù)列組合。比如說,INDEX(A, B, C)可以當(dāng)做A或(A, B)的索引來(lái)使用,但不能當(dāng)做B、C或(B, C)的索引來(lái)使用。
6. 索引的長(zhǎng)度
在為CHAR和VARCHAR類型的數(shù)據(jù)列定義索引時(shí),可以把索引的長(zhǎng)度限制為一個(gè)給定的字符個(gè)數(shù)(這個(gè)數(shù)字必須小于這個(gè)字段所允許的最大字符個(gè)數(shù))。這 么做的好處是可以生成一個(gè)尺寸比較小、檢索速度卻比較快的索引文件。在絕大多數(shù)應(yīng)用里,數(shù)據(jù)庫(kù)中的字符串?dāng)?shù)據(jù)大都以各種各樣的名字為主,把索引的長(zhǎng)度設(shè)置 為10~15個(gè)字符已經(jīng)足以把搜索范圍縮小到很少的幾條數(shù)據(jù)記錄了。
在為BLOB和TEXT類型的數(shù)據(jù)列創(chuàng)建索引時(shí),必須對(duì)索引的長(zhǎng)度做出限制;MySQL所允許的最大索引長(zhǎng)度是255個(gè)字符。
全文索引
文本字段上的普通索引只能加快對(duì)出現(xiàn)在字段內(nèi)容最前面的字符串(也就是字段內(nèi)容開頭的字符)進(jìn)行檢索操作。如果字段里存放的是由幾個(gè)、甚至是多個(gè)單詞構(gòu)成 的較大段文字,普通索引就沒什么作用了。這種檢索往往以LIKE %word%的形式出現(xiàn),這對(duì)MySQL來(lái)說很復(fù)雜,如果需要處理的數(shù)據(jù)量很大,響應(yīng)時(shí)間就會(huì)很長(zhǎng)。
這類場(chǎng)合正是全文索引(full-text index)可以大顯身手的地方。在生成這種類型的索引時(shí),MySQL將把在文本中出現(xiàn)的所有單詞創(chuàng)建為一份清單,查詢操作將根據(jù)這份清單去檢索有關(guān)的數(shù) 據(jù)記錄。全文索引即可以隨數(shù)據(jù)表一同創(chuàng)建,也可以等日后有必要時(shí)再使用下面這條命令添加:
ALTER TABLE tablename ADD FULLTEXT(column1, column2)
有了全文索引,就可以用SELECT查詢命令去檢索那些包含著一個(gè)或多個(gè)給定單詞的數(shù)據(jù)記錄了。下面是這類查詢命令的基本語(yǔ)法:
SELECT * FROM tablename
WHERE MATCH(column1, column2) AGAINST(‘word1′, ‘word2′, ‘word3′)
上面這條命令將把column1和column2字段里有word1、word2和word3的數(shù)據(jù)記錄全部查詢出來(lái)。
注:InnoDB 數(shù)據(jù)表是支持全文索引(FULLTEXT INDEX)的,但 有版本限制。
正確結(jié)論:
| MySQL 版本 | InnoDB 是否支持 FULLTEXT 索引? |
|---|---|
| MySQL 5.6 之前(如 5.5、5.1) | ? 不支持,僅 MyISAM 支持 |
| MySQL 5.6 及以后(包括 5.7、8.0、8.4 等) | ? 完全支持 |
到此這篇關(guān)于mysql中添加索引的3種方法及使用注意事項(xiàng)詳解的文章就介紹到這了,更多相關(guān)mysql添加索引方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL中建表時(shí)可空(NULL)和非空(NOT NULL)的用法詳解
這篇文章主要介紹了MySQL中建表時(shí)可空(NULL)和非空(NOT NULL)的用法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
Mysql數(shù)據(jù)庫(kù)5.7升級(jí)到8.4的實(shí)現(xiàn)
很多情況需要升級(jí)MySQL的數(shù)據(jù)庫(kù)版本,本文主要介紹了Mysql數(shù)據(jù)庫(kù)5.7升級(jí)到8.4的實(shí)現(xiàn),文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06
分析Mysql表讀寫、索引等操作的sql語(yǔ)句效率優(yōu)化問題
今天小編就為大家分享一篇關(guān)于分析Mysql表讀寫、索引等操作的sql語(yǔ)句效率優(yōu)化問題,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12
在OneProxy的基礎(chǔ)上實(shí)行MySQL讀寫分離與負(fù)載均衡
基于Libevent機(jī)制實(shí)現(xiàn),單個(gè)實(shí)例可以實(shí)現(xiàn)25萬(wàn)的SQL轉(zhuǎn)發(fā)能力,用一個(gè)OneProxy節(jié)點(diǎn)可以帶動(dòng)整個(gè)MySQL集群,為業(yè)務(wù)發(fā)展貢獻(xiàn)一份力量,下面由小編來(lái)為大家簡(jiǎn)單說說2019-05-05

