一、什么是索引?為什么要建立索引?
索引用于快速找出在某個(gè)列中有一特定值的行,不使用索引,MySQL必須從第一條記錄開(kāi)始讀完整個(gè)表,直到找出相關(guān)的行,表越大,查詢(xún)數(shù)據(jù)所花費(fèi)的時(shí)間就越多,如果表中查詢(xún)的列有一個(gè)索引,MySQL能夠快速到達(dá)一個(gè)位置去搜索數(shù)據(jù)文件,而不必查看所有數(shù)據(jù),那么將會(huì)節(jié)省很大一部分時(shí)間。
例如:有一張person表,其中有2W條記錄,記錄著2W個(gè)人的信息。有一個(gè)Phone的字段記錄每個(gè)人的電話(huà)號(hào)碼,現(xiàn)在想要查詢(xún)出電話(huà)號(hào)碼為xxxx的人的信息。如果沒(méi)有索引,那么將從表中第一條記錄一條條往下遍歷,直到找到該條信息為止。如果有了索引,那么會(huì)將該P(yáng)hone字段,通過(guò)一定的方法進(jìn)行存儲(chǔ),好讓查詢(xún)?cè)撟侄紊系男畔r(shí),能夠快速找到對(duì)應(yīng)的數(shù)據(jù),而不必在遍歷2W條數(shù)據(jù)了。其中MySQL中的索引的存儲(chǔ)類(lèi)型有兩種:BTREE、HASH。 也就是用樹(shù)或者Hash值來(lái)存儲(chǔ)該字段,要知道其中詳細(xì)是如何查找的,就需要會(huì)算法的知識(shí)了。我們現(xiàn)在只需要知道索引的作用,功能是什么就行。
二、MySQL中索引的優(yōu)點(diǎn)和缺點(diǎn)和使用原則
優(yōu)點(diǎn):
1、所有的MySql列類(lèi)型(字段類(lèi)型)都可以被索引,也就是可以給任意字段設(shè)置索引
2、大大加快數(shù)據(jù)的查詢(xún)速度
缺點(diǎn):
1、創(chuàng)建索引和維護(hù)索引要耗費(fèi)時(shí)間,并且隨著數(shù)據(jù)量的增加所耗費(fèi)的時(shí)間也會(huì)增加
2、索引也需要占空間,我們知道數(shù)據(jù)表中的數(shù)據(jù)也會(huì)有最大上線(xiàn)設(shè)置的,如果我們有大量的索引,索引文件可能會(huì)比數(shù)據(jù)文件更快達(dá)到上線(xiàn)值
3、當(dāng)對(duì)表中的數(shù)據(jù)進(jìn)行增加、刪除、修改時(shí),索引也需要?jiǎng)討B(tài)的維護(hù),降低了數(shù)據(jù)的維護(hù)速度。
使用原則:
通過(guò)上面說(shuō)的優(yōu)點(diǎn)和缺點(diǎn),我們應(yīng)該可以知道,并不是每個(gè)字段度設(shè)置索引就好,也不是索引越多越好,而是需要自己合理的使用。
1、對(duì)經(jīng)常更新的表就避免對(duì)其進(jìn)行過(guò)多的索引,對(duì)經(jīng)常用于查詢(xún)的字段應(yīng)該創(chuàng)建索引,
2、數(shù)據(jù)量小的表最好不要使用索引,因?yàn)橛捎跀?shù)據(jù)較少,可能查詢(xún)?nèi)繑?shù)據(jù)花費(fèi)的時(shí)間比遍歷索引的時(shí)間還要短,索引就可能不會(huì)產(chǎn)生優(yōu)化效果。
3、在一同值少的列上(字段上)不要建立索引,比如在學(xué)生表的"性別"字段上只有男,女兩個(gè)不同值。相反的,在一個(gè)字段上不同值較多可以建立索引。
上面說(shuō)的只是很片面的一些東西,索引肯定還有很多別的優(yōu)點(diǎn)或者缺點(diǎn),還有使用原則,先基本上理解索引,然后等以后真正用到了,就會(huì)慢慢知道別的作用。注意,學(xué)習(xí)這張,很重要的一點(diǎn)就是必須先得知道索引是什么,索引是干嘛的,有什么作用,為什么要索引等等,如果不知道,就重復(fù)往上面看看寫(xiě)的文字,好好理解一下。一個(gè)表中很夠創(chuàng)建多個(gè)索引,這些索引度會(huì)被存放到一個(gè)索引文件中(專(zhuān)門(mén)存放索引的地方)
三、索引的分類(lèi)
注意:索引是在存儲(chǔ)引擎中實(shí)現(xiàn)的,也就是說(shuō)不同的存儲(chǔ)引擎,會(huì)使用不同的索引
MyISAM和InnoDB存儲(chǔ)引擎:只支持BTREE索引, 也就是說(shuō)默認(rèn)使用BTREE,不能夠更換MEMORY/HEAP存儲(chǔ)引擎:支持HASH和BTREE索引
? ? ? ?1、索引我們分為四類(lèi)來(lái)講 單列索引(普通索引,唯一索引,主鍵索引)、組合索引、全文索引、空間索引、
? ? ? ?1.1、單列索引:一個(gè)索引只包含單個(gè)列,但一個(gè)表中可以有多個(gè)單列索引。 這里不要搞混淆了。
? ?1.1.1、普通索引:MySQL中基本索引類(lèi)型,沒(méi)有什么限制,允許在定義索引的列中插入重復(fù)值和空值,純粹為了查詢(xún)數(shù)據(jù)更快一點(diǎn)。
? ?1.1.2、唯一索引:索引列中的值必須是唯一的,但是允許為空值,
? ?1.1.3、主鍵索引:是一種特殊的唯一索引,不允許有空值。
? ? ? 1.2、組合索引
在表中的多個(gè)字段組合上創(chuàng)建的索引,只有在查詢(xún)條件中使用了這些字段的左邊字段時(shí),索引才會(huì)被使用,使用組合索引時(shí)遵循最左前綴集合。這個(gè)如果還不明白,等后面舉例講解時(shí)在細(xì)說(shuō)
1.3、全文索引
全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT類(lèi)型字段上使用全文索引,介紹了要求,說(shuō)說(shuō)什么是全文索引,就是在一堆文字中,通過(guò)其中的某個(gè)關(guān)鍵字等,就能找到該字段所屬的記錄行,比如有"你是個(gè)靚仔,靚女 ..." 通過(guò)靚仔,可能就可以找到該條記錄。這里說(shuō)的是可能,因?yàn)槿乃饕氖褂蒙婕傲撕芏嗉?xì)節(jié),我們只需要知道這個(gè)大概意思,如果感興趣進(jìn)一步深入使用它,那么看下面測(cè)試該索引時(shí),會(huì)給出一個(gè)博文,供大家參考。
? 1.4、空間索引
空間索引是對(duì)空間數(shù)據(jù)類(lèi)型的字段建立的索引,MySQL中的空間數(shù)據(jù)類(lèi)型有四種,GEOMETRY、POINT、LINESTRING、POLYGON。在創(chuàng)建空間索引時(shí),使用SPATIAL關(guān)鍵字。要求,引擎為MyISAM,創(chuàng)建空間索引的列,必須將其聲明為NOT NULL。具體細(xì)節(jié)看下面
四、索引操作(創(chuàng)建和刪除)
4.1、創(chuàng)建索引
4.1.1、創(chuàng)建表的時(shí)候創(chuàng)建索引

4.1.1.1、創(chuàng)建普通索引

上面兩種方式創(chuàng)建都可以,通過(guò)這個(gè)例子可以對(duì)比一下格式,就差不多明白格式是什么意思了。

通過(guò)打印結(jié)果,我們?cè)趧?chuàng)建索引時(shí)沒(méi)寫(xiě)索引名的話(huà),會(huì)自動(dòng)幫我們用字段名當(dāng)作索引名。
測(cè)試:看是否使用了索引進(jìn)行查詢(xún)。
EXPLAIN SELECT * FROM book WHERE year_publication = 1990\G;
解釋?zhuān)弘m然表中沒(méi)數(shù)據(jù),但是有EXPLAIN關(guān)鍵字,用來(lái)查看索引是否正在被使用,并且輸出其使用的索引的信息。

id: SELECT識(shí)別符。這是SELECT的查詢(xún)序列號(hào),也就是一條語(yǔ)句中,該select是第幾次出現(xiàn)。在次語(yǔ)句中,select就只有一個(gè),所以是1.
select_type:所使用的SELECT查詢(xún)類(lèi)型,SIMPLE表示為簡(jiǎn)單的SELECT,不實(shí)用UNION或子查詢(xún),就為簡(jiǎn)單的SELECT。也就是說(shuō)在該SELECT查詢(xún)時(shí)會(huì)使用索引。其他取值,PRIMARY:最外面的SELECT.在擁有子查詢(xún)時(shí),就會(huì)出現(xiàn)兩個(gè)以上的SELECT。UNION:union(兩張表連接)中的第二個(gè)或后面的select語(yǔ)句? SUBQUERY:在子查詢(xún)中,第二SELECT。
table:數(shù)據(jù)表的名字。他們按被讀取的先后順序排列,這里因?yàn)橹徊樵?xún)一張表,所以只顯示book
type:指定本數(shù)據(jù)表和其他數(shù)據(jù)表之間的關(guān)聯(lián)關(guān)系,該表中所有符合檢索值的記錄都會(huì)被取出來(lái)和從上一個(gè)表中取出來(lái)的記錄作聯(lián)合。ref用于連接程序使用鍵的最左前綴或者是該鍵不是 primary key 或 unique索引(換句話(huà)說(shuō),就是連接程序無(wú)法根據(jù)鍵值只取得一條記錄)的情況。當(dāng)根據(jù)鍵值只查詢(xún)到少數(shù)幾條匹配的記錄時(shí),這就是一個(gè)不錯(cuò)的連接類(lèi)型。(注意,個(gè)人這里不是很理解,百度了很多資料,全是大白話(huà),等以后用到了這類(lèi)信息時(shí),在回過(guò)頭來(lái)補(bǔ)充,這里不懂對(duì)后面的影響不大。)可能的取值有 system、const、eq_ref、index和All
possible_keys:MySQL在搜索數(shù)據(jù)記錄時(shí)可以選用的各個(gè)索引,該表中就只有一個(gè)索引,year_publication
key:實(shí)際選用的索引
key_len:顯示了mysql使用索引的長(zhǎng)度(也就是使用的索引個(gè)數(shù)),當(dāng) key 字段的值為 null時(shí),索引的長(zhǎng)度就是 null。注意,key_len的值可以告訴你在聯(lián)合索引中mysql會(huì)真正使用了哪些索引。這里就使用了1個(gè)索引,所以為1,
ref:給出關(guān)聯(lián)關(guān)系中另一個(gè)數(shù)據(jù)表中數(shù)據(jù)列的名字。常量(const),這里使用的是1990,就是常量。
? rows:MySQL在執(zhí)行這個(gè)查詢(xún)時(shí)預(yù)計(jì)會(huì)從這個(gè)數(shù)據(jù)表里讀出的數(shù)據(jù)行的個(gè)數(shù)。
extra:提供了與關(guān)聯(lián)操作有關(guān)的信息,沒(méi)有則什么都不寫(xiě)。
上面的一大堆東西能看懂多少看多少,我們最主要的是看possible_keys和key 這兩個(gè)屬性,上面顯示了key為year_publication。說(shuō)明使用了索引。
4.1.1.2、創(chuàng)建唯一索引
CREATE TABLE t1
(
id INT NOT NULL,
name CHAR(30) NOT NULL,
UNIQUE INDEX UniqIdx(id)
);
解釋?zhuān)簩?duì)id字段使用了索引,并且索引名字為UniqIdx。
SHOW CREATE TABLE t1\G; ?

? 要查看其中查詢(xún)時(shí)使用的索引,必須先往表中插入數(shù)據(jù),然后在查詢(xún)數(shù)據(jù),不然查找一個(gè)沒(méi)有的id值,是不會(huì)使用索引的。
INSERT INTO t1 VALUES(1,'xxx');
EXPLAIN SELECT * FROM t1 WHERE id = 1\G;

? 可以看到,通過(guò)id查詢(xún)時(shí),會(huì)使用唯一索引。并且還實(shí)驗(yàn)了查詢(xún)一個(gè)沒(méi)有的id值,則不會(huì)使用索引,我覺(jué)得原因是所有的id應(yīng)該會(huì)存儲(chǔ)到一個(gè)const tables中,到其中并沒(méi)有該id值,那么就沒(méi)有查找的必要了。
4.1.1.3、創(chuàng)建主鍵索引
CREATE TABLE t2
(
id INT NOT NULL,
name CHAR(10),
PRIMARY KEY(id)
);
INSERT INTO t2 VALUES(1,'QQQ');
EXPLAIN SELECT * FROM t2 WHERE id = 1\G;

通過(guò)這個(gè)主鍵索引,我們就應(yīng)該反應(yīng)過(guò)來(lái),其實(shí)我們以前聲明的主鍵約束,就是一個(gè)主鍵索引,只是之前我們沒(méi)學(xué)過(guò),不知道而已。
4.1.1.4、創(chuàng)建單列索引
? ? ? 這個(gè)其實(shí)就不用在說(shuō)了,前面幾個(gè)就是單列索引。
? 4.1.1.5、創(chuàng)建組合索引
組合索引就是在多個(gè)字段上創(chuàng)建一個(gè)索引,創(chuàng)建一個(gè)表t3,在表中的id、name和age字段上建立組合索引
CREATE TABLE t3
(
id INT NOT NULL,
name CHAR(30) NOT NULL,
age INT NOT NULL,
info VARCHAR(255),
INDEX MultiIdx(id,name,age)
);
SHOW CREATE t3\G;

解釋最左前綴
組合索引就是遵從了最左前綴,利用索引中最左邊的列集來(lái)匹配行,這樣的列集稱(chēng)為最左前綴,不明白沒(méi)關(guān)系,舉幾個(gè)例子就明白了,例如,這里由id、name和age3個(gè)字段構(gòu)成的索引,索引行中就按id/name/age的順序存放,索引可以索引下面字段組合(id,name,age)、(id,name)或者(id)。如果要查詢(xún)的字段不構(gòu)成索引最左面的前綴,那么就不會(huì)是用索引,比如,age或者(name,age)組合就不會(huì)使用索引查詢(xún)
在t3表中,查詢(xún)id和name字段
EXPLAIN SELECT * FROM t3 WHERE id = 1 AND name = 'joe'\G;

在t3表中,查詢(xún)(age,name)字段,這樣就不會(huì)使用索引查詢(xún)。來(lái)看看結(jié)果
EXPLAIN SELECT * FROM t3 WHERE age = 3 AND name = 'bob'\G;

4.1.1.6、創(chuàng)建全文索引
? 全文索引可以用于全文搜索,但只有MyISAM存儲(chǔ)引擎支持FULLTEXT索引,并且只為CHAR、VARCHAR和TEXT列服務(wù)。索引總是對(duì)整個(gè)列進(jìn)行,不支持前綴索引,
CREATE TABLE t4
(
id? INT NOT NULL,
name CHAR(30) NOT NULL,
age INT NOT NULL,
info VARCHAR(255),
FULLTEXT INDEX FullTxtIdx(info)
)ENGINE=MyISAM;
SHOW CREATE TABLE t4\G;

使用一下什么叫做全文搜索。就是在很多文字中,通過(guò)關(guān)鍵字就能夠找到該記錄。
INSERT INTO t4 VALUES(8,'AAA',3,'text is so good,hei,my name is bob'),(9,'BBB',4,'my name isgorlr');
SELECT * FROM t4 WHERE MATCH(info) AGAINST('gorlr');

EXPLAIN?SELECT * FROM t4 WHERE MATCH(info) AGAINST('gorlr'); [if !vml]

注意:在使用全文搜索時(shí),需要借助MATCH函數(shù),并且其全文搜索的限制比較多,比如只能通過(guò)MyISAM引擎,比如只能在CHAR,VARCHAR,TEXT上設(shè)置全文索引。比如搜索的關(guān)鍵字默認(rèn)至少要4個(gè)字符,比如搜索的關(guān)鍵字太短就會(huì)被忽略掉。等等,如果你們?cè)趯?shí)驗(yàn)的時(shí)候可能會(huì)實(shí)驗(yàn)不出來(lái)。感興趣的同學(xué)可以看看這篇文章,全文搜索的使用
4.1.1.7、創(chuàng)建空間索引
空間索引也必須使用MyISAM引擎, 并且空間類(lèi)型的字段必須為非空。 這個(gè)空間索引具體能干嘛我也不知道,可能跟游戲開(kāi)發(fā)有關(guān),可能跟別的東西有關(guān),等遇到了自然就知道了,現(xiàn)在只要求能夠創(chuàng)建出來(lái)。
CREATE TABLE t5
(
g GEOMETRY NOT NULL,
SPATIAL INDEX spatIdx(g)
) ENGINE = MyISAM;
SHOW CREATE TABLE t5\G;

4.1.2、在已經(jīng)存在的表上創(chuàng)建索引
格式:ALTER TABLE 表名 ADD[UNIQUE|FULLTEXT|SPATIAL]
[INDEX|KEY] [索引名] (索引字段名)[ASC|DESC]
有了上面的基礎(chǔ),這里就不用過(guò)多陳述了。
命令一:SHOW INDEX FROM 表名\G
查看一張表中所創(chuàng)建的索引
SHOW INDEX FROM book\G;

挑重點(diǎn)講,我們需要了解的就5個(gè),用紅顏色標(biāo)記了的,如果想深入了解,可以去查查該方面的資料,我個(gè)人覺(jué)得,這些等以后實(shí)際工作中遇到了在做詳細(xì)的了解把。
Table:創(chuàng)建索引的表
Non_unique:表示索引非唯一,1代表 非唯一索引, 0代表 唯一索引,意思就是該索引是不是唯一索引
Key_name:索引名稱(chēng)
Seq_in_index 表示該字段在索引中的位置,單列索引的話(huà)該值為1,組合索引為每個(gè)字段在索引定義中的順序(這個(gè)只需要知道單列索引該值就為1,組合索引為別的)
Column_name:表示定義索引的列字段
Sub_part:表示索引的長(zhǎng)度
Null:表示該字段是否能為空值
Index_type:表示索引類(lèi)型
4.1.2.1、為表添加索引
就拿上面的book表來(lái)說(shuō)。本來(lái)已經(jīng)有了一個(gè)year_publication,現(xiàn)在我們?yōu)樵摫碓诩右粋€(gè)普通索引
ALTER TABLE book ADD INDEX BkNameIdx(bookname(30));

看輸出結(jié)果,就能知道,添加索引成功了。
這里只是拿普通索引做個(gè)例子,添加其他索引也是一樣的。依葫蘆畫(huà)瓢而已。這里就不一一做講解了。
4.1.2.2、使用CREATE INDEX創(chuàng)建索引。
格式:CREATE [UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] 索引名稱(chēng) ON 表名(創(chuàng)建索引的字段名[length])[ASC|DESC]
解釋?zhuān)浩鋵?shí)就是換湯不換藥,格式改變了一下而已,做的事情跟上面完全一樣,做一個(gè)例子。
在為book表增加一個(gè)普通索引,字段為authors。
CREATE INDEX BkBookNameIdx ON book(bookname);

SHOW INDEX FROM book\G; //查看book表中的索引

解釋?zhuān)旱谝粭l截圖沒(méi)截到,因?yàn)閳D太大了,這里只要看到有我們新加進(jìn)去的索引就證明成功了。。其他索引也是一樣的創(chuàng)建。
4.2、刪除索引
? 前面講了對(duì)一張表中索引的添加,查詢(xún)的方法。
添加的兩種方式
1在創(chuàng)建表的同時(shí)如何創(chuàng)建索引,
2在創(chuàng)建了表之后如何給表添加索引的兩種方式,
查詢(xún)的方式
?? SHOW INDEX FROM表名\G; \G只是讓輸出的格式更好看
現(xiàn)在來(lái)說(shuō)說(shuō)如何給表刪除索引的兩種操作。
格式一:ALTER TABLE 表名 DROP INDEX 索引名。
很簡(jiǎn)單的語(yǔ)句,現(xiàn)在通過(guò)一個(gè)例子來(lái)看看,還是對(duì)book表進(jìn)行操作,刪除我們剛才為其添加的索引。
1、刪除book表中的名稱(chēng)為BkBookNameIdx的索引。
? ALTER TABLE book DROPINDEX?BkBookNameIdx;

SHOW INDEX FROM book\G; //在查看book表中的索引,就會(huì)發(fā)現(xiàn)BkBookNameIdx這個(gè)索引已經(jīng)不在了

?格式二:DROP INDEX 索引名 ON 表名;
?刪除book表中名為BkNameIdx的索引
DROP INDEX?BkNameIdx ON book;
SHOW INDEX FROM book\G;

五、總結(jié)
MySQL的索引到這里差不多就講完了,總結(jié)一下我們到目前為止應(yīng)該知道哪些東西
1、索引是干嘛的?為什么要有索引?
這個(gè)很重要,需要自己理解一下,不懂就看頂部的講解
2、索引的分類(lèi)
3、索引的操作
給表中創(chuàng)建索引,添加索引,刪除索引,刪除索引