表索引
文章目錄
- 1 索引概述
- 2 創(chuàng)建索引
- 2.1 普通索引
- 2.2 唯一索引
- 2.3 全文索引
- 2.4 多列索引
- 3 索引的常見(jiàn)操作
- 3.1 查看索引
- 3.2 隱藏索引
- 3.3 刪除索引
- 4 索引的設(shè)計(jì)原則
1 索引概述
基本概念:
-
日常生活中,我們經(jīng)常會(huì)在電話號(hào)碼簿中查閱“某人”的電話號(hào)碼,按姓查詢或者按字母排序查詢; 在字典中查閱“某個(gè)詞”的讀音和含義等等,以快速的找到特定記錄。在這里,“姓”和“字母”都可看作是索引, 而按“姓”或者“字母”查詢則是按索引查詢!
-
索引是一種特殊的數(shù)據(jù)庫(kù)結(jié)構(gòu),可以用來(lái)快速查詢數(shù)據(jù)庫(kù)表中的特定記錄,是提高數(shù)據(jù)庫(kù)性能的重要方式。MySQL中,所有的數(shù)據(jù)類型都可以被索引。
-
通過(guò)索引,查詢數(shù)據(jù)時(shí)可以不必讀完記錄的所有信息,而只是查詢索引列,否則數(shù)據(jù)庫(kù)系統(tǒng)將讀取每條記錄的所有信息進(jìn)行匹配。例如,索引相當(dāng)于新華字典的音序表,如果要查“過(guò)”字,如果不適用音序,就需要從字典的第一頁(yè)開始翻幾百頁(yè);如果提取拼音出來(lái),構(gòu)成音序表,就只需要從10多頁(yè)的音序表中直接查找,這樣就可以大大節(jié)省時(shí)間。因此,使用索引可以在很大程度上提高數(shù)據(jù)庫(kù)的查詢速度,有效地提高了數(shù)據(jù)庫(kù)系統(tǒng)的性能。
索引類型:
- 索引包括普通索引、唯一性索引、全文索引、單列索引、多列索引和空間索引等。
索引存儲(chǔ):
- 數(shù)據(jù)庫(kù)底層索引實(shí)現(xiàn)主要有兩種存儲(chǔ)類型,B樹(BTREE)和哈希(HASH)索引,InnoDB和MyISAM 使用BTREE索引;而MEMORY 存儲(chǔ)引擎可以使用BTREE 和HASH 索引,默認(rèn)用BTREE.在沒(méi)有指定的情況下,數(shù)據(jù)庫(kù)使用的引擎是 InnoDB。
索引優(yōu)點(diǎn):
- 可以提高檢索數(shù)據(jù)的速度。
索引缺點(diǎn):
- 創(chuàng)建和維護(hù)索引需要耗費(fèi)時(shí)間,耗費(fèi)時(shí)間的數(shù)量隨著數(shù)據(jù)量的增加而增加;索引需要占用物理空間,每一個(gè)索引要占一定的物理空間;增加、刪除和修改數(shù)據(jù)時(shí),要?jiǎng)討B(tài)地維護(hù)索引,造成數(shù)據(jù)的維護(hù)速度降低了。
使用建議:
- 索引可以提高查詢的速度,但是會(huì)影響插入記錄的速度,因?yàn)橄蛴兴饕谋碇胁迦胗涗洉r(shí),數(shù)據(jù)庫(kù)系統(tǒng)會(huì)按照索引進(jìn)行排序,這樣就降低了插入記錄的速度,插入大量記錄時(shí)的速度影響更加明顯。這種情況下,最好的辦法是先刪除表中的索引,然后插入數(shù)據(jù),插入完成后再創(chuàng)建索引。
2 創(chuàng)建索引
創(chuàng)建索引是指在某個(gè)表的一列或多列上建立一個(gè)索引,以便提高對(duì)表的訪問(wèn)速度。創(chuàng)建索引有3種方式,分別是創(chuàng)建表的時(shí)候創(chuàng)建索引、在已經(jīng)存在的表上創(chuàng)建索引和使用ALTER TABLE語(yǔ)句來(lái)創(chuàng)建索引。本節(jié)將根據(jù)具體的索引分類詳細(xì)的講解這3種創(chuàng)建方法。
2.1 普通索引
所謂普通索引,就是在創(chuàng)建索引時(shí),不附加任何限制條件(唯一、非空等限制)。該類型的索引可以創(chuàng)建在任何數(shù)據(jù)類型的字段上。
創(chuàng)建表時(shí)定義索引 :
CREATE TABLE tablename(propname1 type1,propname2 type2,……propnamen type..n,INDEX | KEY[indexname] (propnamen [(length)] [ ASC | DESC ] ) );其中,參數(shù)INDEX和KEY是用來(lái)指定字段為索引的,兩者選擇其中之一就可以了,作用是一樣的;參數(shù)indexname是索引名字,可省略;參數(shù)propnamen是索引對(duì)應(yīng)的字段的名稱,該字段必須為前面定義好的字段;參數(shù)length是可選參數(shù),其指索引的長(zhǎng)度,必須是字符串類型才可以使用;參數(shù)ASC和DESC都是可選參數(shù),ASC表示升序排列,DESC表示降序排列,如果不指定,則為升序。
示例如下:
mysql> create database school; #創(chuàng)建數(shù)據(jù)庫(kù)school mysql> use school; #選擇數(shù)據(jù)庫(kù)school mysql> create table class(id int, name varchar(128) UNIQUE, teacher varchar(64), INDEX index_no(id DESC)); #創(chuàng)建表class, 并建立為id 字段索引 mysql> show create table class; #查看表結(jié)構(gòu) mysql> insert into class values(1, '一班', 'Martin'); # 插入記錄1 mysql> insert into class values(1, '二班', 'Rock'); # 插入記錄2 mysql> select * from class where id > 0 ; #根據(jù)id查詢記錄,結(jié)果將降序排列已存在的表上創(chuàng)建索引:
方法一:執(zhí)行create 語(yǔ)句。
CREATE INDEX indexname ON tablename (propname [(length)] [ASC|DESC]);參數(shù)INDEX是用來(lái)指定字段為索引,此處不能為KEY;參數(shù)indexname是新創(chuàng)建的索引的名字;參數(shù)tablename是指需要?jiǎng)?chuàng)建索引的表的名稱,該表必須是已經(jīng)存在的,如果不存在,需要先創(chuàng)建;參數(shù)propname指定索引對(duì)應(yīng)的字段的名稱,該字段必須為前面定義好的字段;參數(shù)length是可選參數(shù),表示索引的長(zhǎng)度,必須是字符串類型才可以使用;參數(shù)ASC和DESC都是可選參數(shù),ASC表示升序排列,DESC表示降序排列,默認(rèn)升序。
示例如下:
mysql> create database school; #創(chuàng)建數(shù)據(jù)庫(kù)school mysql> use school; #選擇數(shù)據(jù)庫(kù)school mysql> create table class(id int, name varchar(128) UNIQUE, teacher varchar(64)); #創(chuàng)建表class, 并建立為id 字段索引 mysql> create index index_id on class(id ASC); #追加升序索引 mysql> show create table class; #查看表定義 mysql> insert into class values(1, '一班', 'Martin'); # 插入記錄1 mysql> insert into class values(1, '二班', 'Rock'); # 插入記錄2 mysql> select * from class where id > 0 ; #根據(jù)id查詢記錄,結(jié)果將降序排列方法二: 執(zhí)行ALTER TABLE 語(yǔ)句。
ALTER TABLE tablename ADD INDEX | KEY indexname (propname [(length)] [ASC|DESC]);在上述語(yǔ)句中,參數(shù)tablename是需要?jiǎng)?chuàng)建索引的表;關(guān)鍵字IDNEX或KEY用來(lái)指定創(chuàng)建普通索引;參數(shù)indexname用來(lái)指定所創(chuàng)建的索引名;參數(shù)propname用來(lái)指定索引所關(guān)聯(lián)的字段的名稱;參數(shù)length用來(lái)指定索引的長(zhǎng)度;參數(shù)ASC用來(lái)指定升序排序;參數(shù)DESC用來(lái)指定降序排序。
示例如下:
alter table common_index add index id_index(id desc);2.2 唯一索引
所謂唯一索引,就是在創(chuàng)建索引時(shí),限制索引的字段值必須是唯一的。通過(guò)該類型的索引可以比普通索引更快速地查詢某條記錄。
創(chuàng)建表時(shí)定義索引:
CREATE TABLE tablename(propname1 type1,……propnamen type..n,UNIQUE INDEX | KEY [indexname] (propnamen [(length)] [ ASC | DESC ] ) );注意:參數(shù)UNIQUE INDEX和UNIQUE KEY是用來(lái)指定字段為索引的,兩者選擇其中之一即可;參數(shù)indexname是索引名字,可省略;參數(shù)propnamen是索引對(duì)應(yīng)的字段的名稱,該字段必須為前面定義好的字段且必須定義為 UNIQUE 約束;參數(shù)length是可選參數(shù),其指索引的長(zhǎng)度,必須是字符串類型才可以使用;參數(shù)ASC和DESC都是可選參數(shù),ASC表示升序排列,DESC表示降序排列,如果不指定,則為升序。
已存在的表上創(chuàng)建索引:
方法一:
方法二:
ALTER TABLE tablename ADD UNIQUE INDEX | KEY indexname (propname [(length)] [ASC|DESC]);需要注意:使用了unique約束之后就相當(dāng)于使用了唯一索引,起到的效果相同。
下圖為只使用unique約束的查詢結(jié)果:
添加了唯一約束之后的查詢結(jié)果:
可以看到效果一樣。
2.3 全文索引
全文索引主要對(duì)字符串類型建立基于分詞的索引,主要是基于CHAR、VARCHAR和TEXT的字段上,以便能夠更加快速地查詢數(shù)據(jù)量較大的字符串類型的字段。
全文索引以詞為基礎(chǔ)的,MySQL默認(rèn)的分詞是所有非字母和數(shù)字的特殊符號(hào)都是分詞符。
MySQL從3.23版本開始支持全文索引,MySQL5.6以前只能在存儲(chǔ)引擎為MyISAM的數(shù)據(jù)表上創(chuàng)建全文索引,5.6之后InnoDB開始支持全文索引(5.7之后支持中文全文索引) 。在默認(rèn)情況下,全文索引的搜索執(zhí)行方式為不區(qū)分大小寫,如果全文索引所關(guān)聯(lián)的字段為二進(jìn)制數(shù)據(jù)類型,就以區(qū)分大小寫的搜索方式執(zhí)行。
創(chuàng)建表時(shí)定義索引:
CREATE TABLE tablename(propname1 type1,propname2 type2,……propnamen type..n,FULLTEXT INDEX | KEY[indexname] (propnamen [(length)] ) );示例如下:
mysql> create database school; #創(chuàng)建數(shù)據(jù)庫(kù)school mysql> use school; #選擇數(shù)據(jù)庫(kù)school mysql>create table class(id int, name varchar(128) UNIQUE, teacher varchar(64),comment varchar(1024),FULLTEXT INDEX index_comm(comment)); #創(chuàng)建表class, 并建立為comment 字段為全文索引 mysql> insert into class values(1,'1班','Martin','我是一個(gè)兵,來(lái)自老百姓!'); # 插入記錄1 mysql> insert into class values(2,'2班','Rock','此班主任畢業(yè)自唐僧系'); # 插入記錄2 mysql> insert into class values(3,'3班','Janny','I''m Miss Zhang.'); #插入記錄3 mysql> select * from class where match(comment) AGAINST('我是一個(gè)兵');#利用全文檢索索引快速查詢記錄已存在的表上創(chuàng)建索引:
方法一: 執(zhí)行create 語(yǔ)句。
在MySQL中創(chuàng)建全文索引除了通過(guò)SQL語(yǔ)句FULLTEXT INDEX來(lái)實(shí)現(xiàn)外,還可以通過(guò)SQL語(yǔ)句CREATE FULLTEXT INDEX來(lái)實(shí)現(xiàn),其語(yǔ)法形式如下:
CREATE FULLTEXT INDEX indexname ON tablename( propname1 [ ( length ) ] );在上述語(yǔ)句中,關(guān)鍵字CREATE FULLTEXT INDEX表示用來(lái)創(chuàng)建全文索引。
如下例表已存在,可通過(guò)CREATE語(yǔ)句創(chuàng)建全文索引:
mysql> create database school; #創(chuàng)建數(shù)據(jù)庫(kù)school mysql> use school; #選擇數(shù)據(jù)庫(kù)school mysql> create table class(id int, name varchar(128) UNIQUE, teacher varchar(64)); #創(chuàng)建表class, 并建立為id 字段索引 mysql> create FULLTEXT index index_teacher on class(teacher ); #追加全文索引 mysql> show create table class; #查看表定義方法二: 執(zhí)行ALTER TABLE 語(yǔ)句。
除了上述兩種方式來(lái)創(chuàng)建全文索引外,在MySQL中創(chuàng)建全文索引還可以通過(guò)SQL語(yǔ)句ALTER來(lái)實(shí)現(xiàn),其語(yǔ)法形式如下:
ALTER TABLE tablename ADD FULLTEXT INDEX|KEY indexname(propname [(length)]);使用場(chǎng)景:
根據(jù)全文索引字段進(jìn)行全文檢索數(shù)據(jù):
MySQL8 中文分詞支持:
配置文件my.ini(Windows 10默認(rèn)路徑: C:\ProgramData\MySQL\MySQL Server 8.0) 中增加如下配置項(xiàng),同時(shí)重啟MySQL80 服務(wù):
[mysqld]
ngram_token_size=2
2.4 多列索引
多列索引,是指在創(chuàng)建索引時(shí)所關(guān)聯(lián)的字段不是一個(gè)字段,而是多個(gè)字段,雖然可以通過(guò)所關(guān)聯(lián)的字段進(jìn)行查詢,但是只有查詢條件中使用了所關(guān)聯(lián)字段中的第一個(gè)字段,多列索引才會(huì)被使用。
創(chuàng)建表時(shí)定義索引 :
CREATE TABLE tablename(propname1 type1,……propnamen type..n,INDEX | KEY [indexname] (propname1 [(length)] [ ASC | DESC ],Propname2 [(length)] [ ASC | DESC ], ... ... Propnamen [(length)] [ ASC | DESC ]) );注意:和普通索引定義基本相同,不同之處就是增加了多個(gè)索引列。
實(shí)例如下:
mysql> create database school; #創(chuàng)建數(shù)據(jù)庫(kù)school mysql> use school; #選擇數(shù)據(jù)庫(kù)school mysql> create table class(id int, name varchar(128) UNIQUE, teacher varchar(64), INDEX index_mult_columns(id, teacher)); #創(chuàng)建表class, 并建立包含id,teacher字段的多列索引 mysql> show create table class; #查看表定義 mysql> insert into class values(1, '一班', 'Martin'); # 插入記錄1 mysql> insert into class values(1, '二班', 'Rock'); # 插入記錄2 mysql> select * from class where id > 0 ; #僅根據(jù)id查詢記錄會(huì)啟用多列索引已存在的表上創(chuàng)建索引:
方法一: 執(zhí)行create 語(yǔ)句。
CREATE INDEX indexnameON tablename( propname1 [(length)] [ ASC | DESC ], Propname2 [(length)] [ ASC | DESC ], ... ... Propnamen [(length)] [ ASC | DESC ] );在上述語(yǔ)句中,關(guān)鍵字CREATE INDEX表示用來(lái)創(chuàng)建多列索引。
如下例表已存在,可通過(guò)CREATE語(yǔ)句創(chuàng)建多列索引:
mysql> create database school; #創(chuàng)建數(shù)據(jù)庫(kù)school mysql> use school; #選擇數(shù)據(jù)庫(kù)school mysql> create table class(id int, name varchar(128) UNIQUE, teacher varchar(64)); #創(chuàng)建表class, 并建立為id 字段索引 mysql> create index index_id on class(id, name ); #追加多列索引 mysql> show create table class; #查看表定義方法二: 執(zhí)行ALTER TABLE 語(yǔ)句。
除了上述兩種方式來(lái)創(chuàng)建全文索引外,在MySQL中創(chuàng)建全文索引還可以通過(guò)SQL語(yǔ)句ALTER來(lái)實(shí)現(xiàn),其語(yǔ)法形式如下:
ALTER TABLE tablenameADD INDEX|KEY indexname(propname1 [(length)] [ ASC | DESC ], Propname2 [(length)] [ ASC | DESC ], ... ... Propnamen [(length)] [ ASC | DESC ] );3 索引的常見(jiàn)操作
3.1 查看索引
看所索引可以使用如下語(yǔ)句:
EXPLAIN 查詢語(yǔ)句
輸出結(jié)果:
- key:實(shí)際使用的索引。如果為NULL,則沒(méi)有使用索引。
- possible_keys:顯示可能應(yīng)用在這張表中的索引,一個(gè)或多個(gè)。查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢實(shí)際使用。
- key_len: 表示索引中使用的字節(jié)數(shù),可通過(guò)該列計(jì)算查詢中使用的索引的長(zhǎng)度。此值越短越好!
3.2 隱藏索引
MySQL 8開始支持隱藏索引。隱藏索引提供了更人性化的數(shù)據(jù)庫(kù)操作。
隱藏索引,顧名思義,讓索引暫時(shí)不可見(jiàn),不會(huì)被優(yōu)化器使用。默認(rèn)情況下索引是可見(jiàn)的。隱藏索引可以用來(lái)測(cè)試索引的性能。驗(yàn)證索引的必要性時(shí)不需要?jiǎng)h除索引,可以先將索引隱藏,如果優(yōu)化器性能無(wú)影響就可以真正地刪除索引。
ALTER TABLE tablename ALTER INDEX index_name INVISIBLE; #隱藏索引 ALTER TABLE tablename ALTER INDEX index_name VISIBLE; #取消隱藏3.3 刪除索引
所謂刪除索引,就是刪除表中已經(jīng)創(chuàng)建的索引。之所以要?jiǎng)h除索引,是因?yàn)檫@些索引會(huì)降低表的更新速度,影響數(shù)據(jù)庫(kù)的性能。
在MySQL中刪除索引通過(guò)SQL語(yǔ)句DROP INDEX來(lái)實(shí)現(xiàn),其語(yǔ)法形式如下:
修改索引: 先刪除,后增加。
4 索引的設(shè)計(jì)原則
為了使索引的使用效率更高,在創(chuàng)建索引時(shí),必須考慮在哪些字段上創(chuàng)建索引和創(chuàng)建什么類型的索引。本節(jié)將介紹一些索引的設(shè)計(jì)原則。
1. 選擇唯一性索引。
唯一性索引的值是唯一的,可以更快速地通過(guò)該索引來(lái)確定某條記錄。例如,學(xué)生表中學(xué)號(hào)是具有唯一性的字段,為該字段建立唯一性索引可以很快確定某個(gè)學(xué)生的信息,如果使用姓名的話,可能存在同名現(xiàn)象,從而降低查詢速度。
2. 為經(jīng)常需要排序、分組和聯(lián)合操作的字段建立索引。
經(jīng)常需要使用ORDER BY、GROUP BY、DISTINCT和UNION等操作的字段,排序操作會(huì)浪費(fèi)很多時(shí)間,如果為其建立索引,可以有效地避免排序操作。
3. 為經(jīng)常作為查詢條件的字段建立索引。
如果某個(gè)字段經(jīng)常用來(lái)做查詢條件,那么該字段的查詢速度會(huì)影響整個(gè)表的查詢速度,為這樣的字段建立索引可以提高整個(gè)表的查詢速度。
4.限制索引的數(shù)目。
索引的數(shù)目不是越多越好。每個(gè)索引都需要占用磁盤空間,索引越多,需要的磁盤空間就越大,修改表時(shí),對(duì)索引的重構(gòu)和更新很麻煩。
5. 盡量使用數(shù)據(jù)量少的索引。
如果索引的值很長(zhǎng),那么查詢的速度會(huì)受到影響。例如,對(duì)一個(gè)CHAR(100)類型的字段進(jìn)行全文檢索需要的時(shí)間肯定要比對(duì)CHAR(10)類型的字段需要的時(shí)間多。
6. 盡量使用前綴來(lái)索引。
如果索引的值很長(zhǎng),最好使用值的前綴來(lái)索引。例如,TEXT和BLOG類型的字段,進(jìn)行全文檢索會(huì)很浪費(fèi)時(shí)間,如果只檢索字段前面的若干字符,這樣可以提高檢索速度。
7. 刪除不再使用或者很少使用的索引。
表中的數(shù)據(jù)被大量更新,或者數(shù)據(jù)的使用方式被改變后,原有的一些索引可能不再需要。數(shù)據(jù)庫(kù)管理員應(yīng)當(dāng)定期找出這些索引,將它們刪除,從而減少索引對(duì)更新操作的影響。
參考資料:
總結(jié)
- 上一篇: 8×8的T55/E1轮式
- 下一篇: 封装Client