MySQL索引詳細(xì)介紹

一、什么是索引?為什么要建立索引?

索引用于快速找出在某個(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)建索引,添加索引,刪除索引,刪除索引

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • MYSQL 基礎(chǔ)知識(shí) 1 MySQL數(shù)據(jù)庫(kù)概要 2 簡(jiǎn)單MySQL環(huán)境 3 數(shù)據(jù)的存儲(chǔ)和獲取 4 MySQL基本操...
    Kingtester閱讀 8,050評(píng)論 5 115
  • 觀(guān)其大綱 page 01 基礎(chǔ)知識(shí) 1 MySQL數(shù)據(jù)庫(kù)概要 2 簡(jiǎn)單MySQL環(huán)境 3 數(shù)據(jù)的存儲(chǔ)和獲取 4 M...
    周少言閱讀 3,244評(píng)論 0 33
  • 1 “媽?zhuān)∧趺戳???母親突然打電話(huà)說(shuō)她生病了,楚楚便風(fēng)風(fēng)火火地從城里趕回家,連午飯都沒(méi)來(lái)得及吃。 “哎,楚楚你...
    蕓糖閱讀 658評(píng)論 1 8
  • 李白只是一只修煉了上千年的狐妖。一天,淘氣的李白喬裝打扮了一下。去京城玩玩。他剛進(jìn)京城,就看見(jiàn)化做凡人的龍族少主韓...
    信白愛(ài)戀閱讀 4,295評(píng)論 0 5
  • “有的時(shí)候,覺(jué)得自己像個(gè)小丑。 你看得見(jiàn)我快樂(lè),你看不見(jiàn)我的悲傷?!?有一種快樂(lè),是裝的,為了取悅別人。只要你勤于...
    文鳴人閱讀 670評(píng)論 0 3

友情鏈接更多精彩內(nèi)容