MySQL(五) MySQL中的索引詳講

      序言html

         以前寫到MySQL對錶的增刪改查(查詢最爲重要)後,就感受MySQL就差很少學完了,沒有想繼續學下去的心態了,緣由多是因爲別人的影響,以爲對於MySQL來講,知道了一些複雜的查詢,就夠了,可是我認爲,無論有沒有用,如今學着不懂的東西,說明就是本身薄弱的地方,多學才能比別人更強mysql

                                        --WZY算法

 

1、什麼是索引?爲何要創建索引?sql

       索引用於快速找出在某個列中有一特定值的行,不使用索引,MySQL必須從第一條記錄開始讀完整個表,直到找出相關的行,表越大,查詢數據所花費的時間就越多,若是表中查詢的列有一個索引,MySQL可以快速到達一個位置去搜索數據文件,而沒必要查看全部數據,那麼將會節省很大一部分時間。函數

       例如:有一張person表,其中有2W條記錄,記錄着2W我的的信息。有一個Phone的字段記錄每一個人的電話號碼,如今想要查詢出電話號碼爲xxxx的人的信息。學習

          若是沒有索引,那麼將從表中第一條記錄一條條往下遍歷,直到找到該條信息爲止。測試

          若是有了索引,那麼會將該Phone字段,經過必定的方法進行存儲,好讓查詢該字段上的信息時,可以快速找到對應的數據,而沒必要在遍歷2W條數據了。其中MySQL中的索引的存儲類型有兩種:BTREE、HASH。 也就是用樹或者Hash值來存儲該字段,要知道其中詳細是如何查找的,就須要會算法的知識了。咱們如今只須要知道索引的做用,功能是什麼就行。優化

 

 

2、MySQL中索引的優勢和缺點和使用原則spa

      優勢:3d

       二、全部的MySql列類型(字段類型)均可以被索引,也就是能夠給任意字段設置索引

       三、大大加快數據的查詢速度

      缺點:

       一、建立索引和維護索引要耗費時間,而且隨着數據量的增長所耗費的時間也會增長

       二、索引也須要佔空間,咱們知道數據表中的數據也會有最大上線設置的,若是咱們有大量的索引,索引文件可能會比數據文件更快達到上線值

       三、當對錶中的數據進行增長、刪除、修改時,索引也須要動態的維護,下降了數據的維護速度。

      使用原則:

            經過上面說的優勢和缺點,咱們應該能夠知道,並非每一個字段度設置索引就好,也不是索引越多越好,而是須要本身合理的使用。

       一、對常常更新的表就避免對其進行過多的索引,對常常用於查詢的字段應該建立索引,

       二、數據量小的表最好不要使用索引,由於因爲數據較少,可能查詢所有數據花費的時間比遍歷索引的時間還要短,索引就可能不會產生優化效果。

       三、在一同值少的列上(字段上)不要創建索引,好比在學生表的"性別"字段上只有男,女兩個不一樣值。相反的,在一個字段上不一樣值較多但是創建索引。

  

      上面說的只是很片面的一些東西,索引確定還有不少別的優勢或者缺點,還有使用原則,先基本上理解索引,而後等之後真正用到了,就會慢慢知作別的做用。注意,學習這張,很重要的一點就是必須先得知道索引是什麼,索引是幹嗎的,有什麼做用,爲何要索引等等,若是不知道,就重複往上面看看寫的文字,好好理解一下。一個表中很夠建立多個索引,這些索引度會被存放到一個索引文件中(專門存放索引的地方)

 

 

3、索引的分類  

       注意:索引是在存儲引擎中實現的,也就是說不一樣的存儲引擎,會使用不一樣的索引

            MyISAM和InnoDB存儲引擎:只支持BTREE索引, 也就是說默認使用BTREE,不可以更換

            MEMORY/HEAP存儲引擎:支持HASH和BTREE索引

       一、索引咱們分爲四類來說 單列索引(普通索引,惟一索引,主鍵索引)、組合索引、全文索引、空間索引、

          1.一、單列索引:一個索引只包含單個列,但一個表中能夠有多個單列索引。 這裏不要搞混淆了。

             1.1.一、普通索引

                  MySQL中基本索引類型,沒有什麼限制,容許在定義索引的列中插入重複值和空值,純粹爲了查詢數據更快一點。

             1.1.二、惟一索引

                  索引列中的值必須是惟一的,可是容許爲空值,

             1.1.三、主鍵索引

                  是一種特殊的惟一索引,不容許有空值。

          1.二、組合索引

               在表中的多個字段組合上建立的索引,只有在查詢條件中使用了這些字段的左邊字段時,索引纔會被使用,使用組合索引時遵循最左前綴集合。這個若是還不明白,等後面舉例講解時在細說 

          1.三、全文索引

               全文索引,只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT類型字段上使用全文索引,介紹了要求,說說什麼是全文索引,就是在一堆文字中,經過其中的某個關鍵字等,就能找到該字段所屬的記錄行,好比有"你是個大煞筆,二貨 ..." 經過大煞筆,可能就能夠找到該條記錄。這裏說的是可能,由於全文索引的使用涉及了不少細節,咱們只須要知道這個大概意思,若是感興趣進一步深刻使用它,那麼看下面測試該索引時,會給出一個博文,供你們參考。

          1.四、空間索引

               空間索引是對空間數據類型的字段創建的索引,MySQL中的空間數據類型有四種,GEOMETRY、POINT、LINESTRING、POLYGON。

               在建立空間索引時,使用SPATIAL關鍵字。

               要求,引擎爲MyISAM,建立空間索引的列,必須將其聲明爲NOT NULL。具體細節看下面   

 

4、索引操做(建立和刪除)

      4.一、建立索引

          4.1.一、建立表的時候建立索引

            格式:CREATE TABLE 表名[字段名 數據類型]  [UNIQUE|FULLTEXT|SPATIAL|...] [INDEX|KEY] [索引名字] (字段名[length])   [ASC|DESC]

               |--------------------------------------|  |-----------------------------------| |------------| |---------| |---------------|    |------------|

                    普通建立表語句        設置什麼樣的索引(惟1、全文等)  索引關鍵字  索引名字 對哪一個字段設置索引  對索引進行排序 

              4.1.1.一、建立普通索引              

                CREATE TABLE book                    CREATE TABLE book

                (                              (

                  bookid INT NOT NULL,                  bookid INT NOT NULL,

                  bookname VARCHAR(255) NOT NULL,           bookname VARCHAR(255) NOT NULL,

                  authors VARCHAR(255) NOT NULL,             authors VARCHAR(255) NOT NULL,

                  info VARCHAR(255) NULL,                info VARCHAR(255) NULL,

                  comment VARCHAR(255) NULL,             comment VARCHAR(255) NULL, 

                  year_publication YEAR NOT NULL,            year_publication YEAR NOT NULL,

                  INDEX(year_publication)                 KEY(year_publication) 

                );                              );

              上面兩種方式建立度能夠,經過這個例子能夠對比一下格式,就差很少明白格式是什麼意思了。

                        

                經過打印結果,咱們在建立索引時沒寫索引名的話,會自動幫咱們用字段名看成索引名。

                測試:看是否使用了索引進行查詢。

                  EXPLAIN SELECT * FROM book WHERE year_publication = 1990\G;

                  解釋:雖然表中沒數據,可是有EXPLAIN關鍵字,用來查看索引是否正在被使用,而且輸出其使用的索引的信息。

                       

                    id: SELECT識別符。這是SELECT的查詢序列號,也就是一條語句中,該select是第幾回出現。在次語句中,select就只有一個,因此是1.

                    select_type:所使用的SELECT查詢類型,SIMPLE表示爲簡單的SELECT,不實用UNION或子查詢,就爲簡單的SELECT。也就是說在該SELECT查詢時會使用索引。其餘取值,PRIMARY:最外面的SELECT.在擁有子查詢時,就會出現兩個以上的SELECT。UNION:union(兩張錶鏈接)中的第二個或後面的select語句  SUBQUERY:在子查詢中,第二SELECT。

                    table:數據表的名字。他們按被讀取的前後順序排列,這裏由於只查詢一張表,因此只顯示book

                    type:指定本數據表和其餘數據表之間的關聯關係,該表中全部符合檢索值的記錄都會被取出來和從上一個表中取出來的記錄做聯合。ref用於鏈接程序使用鍵的最左前綴或者是該鍵不是 primary key 或 unique索引(換句話說,就是鏈接程序沒法根據鍵值只取得一條記錄)的狀況。當根據鍵值只查詢到少數幾條匹配的記錄時,這就是一個不錯的鏈接類型。(注意,我的這裏不是很理解,百度了不少資料,全是大白話,等之後用到了這類信息時,在回過頭來補充,這裏不懂對後面的影響不大。)可能的取值有 system、const、eq_ref、index和All

                    possible_keys:MySQL在搜索數據記錄時能夠選用的各個索引,該表中就只有一個索引,year_publication

                    key:實際選用的索引

                    key_len:顯示了mysql使用索引的長度(也就是使用的索引個數),當 key 字段的值爲 null時,索引的長度就是 null。注意,key_len的值能夠告訴你在聯合索引中mysql會真正使用了哪些索引。這裏就使用了1個索引,因此爲1,

                    ref:給出關聯關係中另外一個數據表中數據列的名字。常量(const),這裏使用的是1990,就是常量。

                    rows:MySQL在執行這個查詢時預計會從這個數據表裏讀出的數據行的個數。

                    extra:提供了與關聯操做有關的信息,沒有則什麼都不寫。   

                  上面的一大堆東西能看懂多少看多少,咱們最主要的是看possible_keys和key 這兩個屬性,上面顯示了key爲year_publication。說明使用了索引。

             4.1.1.二、建立惟一索引  

                CREATE TABLE t1

                (

                  id INT NOT NULL,

                  name CHAR(30) NOT NULL,

                  UNIQUE INDEX UniqIdx(id)

                );  

                解釋:對id字段使用了索引,而且索引名字爲UniqIdx。

                SHOW CREATE TABLE t1\G;

                      

                  要查看其中查詢時使用的索引,必須先往表中插入數據,而後在查詢數據,否則查找一個沒有的id值,是不會使用索引的。

                INSERT INTO t1 VALUES(1,'xxx');

                EXPLAIN SELECT * FROM t1 WHERE id = 1\G;

                      

                能夠看到,經過id查詢時,會使用惟一索引。而且還實驗了查詢一個沒有的id值,則不會使用索引,我以爲緣由是全部的id應該會存儲到一個const tables中,到其中並無該id值,那麼就沒有查找的必要了。   

 

            4.1.1.三、建立主鍵索引

                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;

                      

                 經過這個主鍵索引,咱們就應該反應過來,其實咱們之前聲明的主鍵約束,就是一個主鍵索引,只是以前咱們沒學過,不知道而已。

             4.1.1.四、建立單列索引 

                 這個其實就不用在說了,前面幾個就是單列索引。

 

             4.1.1.五、建立組合索引

                組合索引就是在多個字段上建立一個索引

                建立一個表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;

                      

                解釋最左前綴

                      組合索引就是聽從了最左前綴,利用索引中最左邊的列集來匹配行,這樣的列集稱爲最左前綴,不明白不要緊,舉幾個例子就明白了,例如,這裏由id、name和age3個字段構成的索引,索引行中就按id/name/age的順序存放,索引能夠索引下面字段組合(id,name,age)、(id,name)或者(id)。若是要查詢的字段不構成索引最左面的前綴,那麼就不會是用索引,好比,age或者(name,age)組合就不會使用索引查詢

                在t3表中,查詢id和name字段

                EXPLAIN SELECT * FROM t3 WHERE id = 1 AND name = 'joe'\G;

                      

                在t3表中,查詢(age,name)字段,這樣就不會使用索引查詢。來看看結果

                EXPLAIN SELECT * FROM t3 WHERE age = 3 AND name = 'bob'\G;

                      

            4.1.1.六、建立全文索引

                全文索引能夠用於全文搜索,但只有MyISAM存儲引擎支持FULLTEXT索引,而且只爲CHAR、VARCHAR和TEXT列服務。索引老是對整個列進行,不支持前綴索引,

                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;

                    

               使用一下什麼叫作全文搜索。就是在不少文字中,經過關鍵字就可以找到該記錄。

                  INSERT INTO t4 VALUES(8,'AAA',3,'text is so good,hei,my name is bob'),(9,'BBB',4,'my name is gorlr');

                  SELECT * FROM t4 WHERE MATCH(info) AGAINST('gorlr');

                    

                  EXPLAIN SELECT * FROM t4 WHERE MATCH(info) AGAINST('gorlr');

                    

                  注意:在使用全文搜索時,須要藉助MATCH函數,而且其全文搜索的限制比較多,好比只能經過MyISAM引擎,好比只能在CHAR,VARCHAR,TEXT上設置全文索引。好比搜索的關鍵字默認至少要4個字符,好比搜索的關鍵字過短就會被忽略掉。等等,若是大家在實驗的時候可能會實驗不出來。感興趣的同窗能夠看看這篇文章,全文搜索的使用

 

            4.1.1.七、建立空間索引

                空間索引也必須使用MyISAM引擎, 而且空間類型的字段必須爲非空。 這個空間索引具體能幹嗎我也不知道,可能跟遊戲開發有關,可能跟別的東西有關,等遇到了天然就知道了,如今只要求可以建立出來。

                CREATE TABLE t5

                (

                  g GEOMETRY NOT NULL,

                  SPATIAL INDEX spatIdx(g)

                ) ENGINE = MyISAM;

                SHOW CREATE TABLE t5\G;

                    

          4.1.二、在已經存在的表上建立索引

              格式:ALTER TABLE 表名 ADD[UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [索引名] (索引字段名)[ASC|DESC]

                 有了上面的基礎,這裏就不用過多陳述了。

              命令一:SHOW INDEX FROM 表名\G  

                  查看一張表中所建立的索引

                  SHOW INDEX FROM book\G;

                      

                  挑重點講,咱們須要瞭解的就5個,用紅顏色標記了的,若是想深刻了解,能夠去查查該方面的資料,我我的以爲,這些等之後實際工做中遇到了在作詳細的瞭解把。

                  Table:建立索引的表

                  Non_unique:表示索引非惟一,1表明 非惟一索引, 0表明 惟一索引,意思就是該索引是否是惟一索引

                  Key_name:索引名稱

                  Seq_in_index 表示該字段在索引中的位置,單列索引的話該值爲1,組合索引爲每一個字段在索引定義中的順序(這個只須要知道單列索引該值就爲1,組合索引爲別的)

                  Column_name:表示定義索引的列字段

                  Sub_part:表示索引的長度

                  Null:表示該字段是否能爲空值

                  Index_type:表示索引類型

             4.1.2.一、爲表添加索引

                就拿上面的book表來講。原本已經有了一個year_publication,如今咱們爲該表在加一個普通索引

                ALTER TABLE book ADD INDEX BkNameIdx(bookname(30));

                    

                看輸出結果,就能知道,添加索引成功了。

                這裏只是拿普通索引作個例子,添加其餘索引也是同樣的。依葫蘆畫瓢而已。這裏就不一一作講解了。

             4.1.2.二、使用CREATE INDEX建立索引。

                格式:CREATE [UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] 索引名稱 ON 表名(建立索引的字段名[length])[ASC|DESC]

                  解釋:其實就是換湯不換藥,格式改變了一下而已,作的事情跟上面徹底同樣,作一個例子。

                在爲book表增長一個普通索引,字段爲authors。

                CREATE INDEX BkBookNameIdx ON book(bookname);

                    

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

                    

                  解釋:第一條截圖沒截到,由於圖太大了,這裏只要看到有咱們新加進去的索引就證實成功了。。其餘索引也是同樣的建立。

      4.二、刪除索引

            前面講了對一張表中索引的添加,查詢的方法。

              添加的兩種方式

                1在建立表的同時如何建立索引,

                2在建立了表以後如何給表添加索引的兩種方式,

              查詢的方式

                SHOW INDEX FROM 表名\G;  \G只是讓輸出的格式更好看

              如今來講說如何給表刪除索引的兩種操做。

                格式一:ALTER TABLE 表名 DROP INDEX 索引名

                  很簡單的語句,如今經過一個例子來看看,仍是對book表進行操做,刪除咱們剛纔爲其添加的索引。

                一、刪除book表中的名稱爲BkBookNameIdx的索引。

                  ALTER TABLE book DROP INDEX BkBookNameIdx;

                       

                  SHOW INDEX FROM book\G;  //在查看book表中的索引,就會發現BkBookNameIdx這個索引已經不在了

                      

 

                   格式二:DROP INDEX 索引名 ON 表名;

                       刪除book表中名爲BkNameIdx的索引

                      DROP INDEX BkNameIdx ON book;

                       SHOW INDEX FROM book\G;

                        

 

5、總結

      MySQL的索引到這裏差很少就講完了,總結一下咱們到目前爲止應該知道哪些東西

        一、索引是幹嗎的?爲何要有索引?

            這個很重要,須要本身理解一下,不懂就看頂部的講解

        二、索引的分類

        三、索引的操做

            給表中建立索引,添加索引,刪除索引,刪除索引  

相關文章
相關標籤/搜索