MySQL索引

什麼是索引

在MySQL中,索引(index)也叫作「鍵(key)」,它是存儲引擎用於快速找到記錄的一種數據結構。

在mysql中有多種索引類型

  • 主鍵索引
    也簡稱主鍵。它能夠提升查詢效率,並提供惟一性約束。一張表中只能有一個主鍵。被標誌爲自動增加的字段必定是主鍵,但主鍵不必定是自動增加。通常把主鍵定義在無心義的字段上(如:編號),主鍵的數據類型最好是數值。
  • 普通索引(常規索引(INDEX或KEY))
    普通索引通常是在建表後再添加的
    • 單列索引mysql

      ALTER TABLE `testDB`.`user` 
       ADD INDEX `idx_name`(`name`) USING BTREE
    • 組合索引redis

      ADD INDEX `idx_mult`(`name`, `address`) USING BTREE

    組合索引最左前綴原則
    例如上面咱們建立了一個name, address的組合索引
    select * from user where name = ‘xxx’ 此時,會走索引
    select * from user where address = ‘xxx’ 則不會走索引算法

  • 全文索引
    首先,全文索引主要針對文本文件,好比文章,標題,全文索引只有MyISAM有效(mysql5.6以後InnoDB也支持了全文索引)sql

create table c(  
            id int primary key auto_increment ,  
            title varchar(20),  
            content text,  
            fulltext(title,content)  
       )engine=myisam charset utf8;  
        insert into c(title,content) values  
            ('MySQL Tutorial','DBMS stands for DataBase ...'),  
            ('How To Use MySQL Well','After you went through a ...'),  
            ('Optimizing MySQL','In this tutorial we will show ...'),  
            ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),  
            ('MySQL vs. YourSQL','In the following database comparison ...'),  
            ('MySQL Security','When configured properly, MySQL ...');
  • 惟一索引數據庫

    ADD UNIQUE INDEX `idx_unique`(`en_name`);

    主鍵是一種約束,惟一索引是一種索引,二者在本質上是不一樣的。
    主鍵建立後必定包含一個惟一性索引,惟一性索引並不必定就是主鍵。
    惟一性索引列容許空值,而主鍵列不容許爲空值。
    主鍵列在建立時,已經默認爲空值 + 惟一索引了。
    主鍵能夠被其餘表引用爲外鍵,而惟一索引不能。
    一個表最多隻能建立一個主鍵,但能夠建立多個惟一索引。
    主鍵更適合那些不容易更改的惟一標識,如自動遞增列、身份證號等。緩存

MySQL索引方式?

通常有四種索引方式(BTREE,RTREE, HASH ,FULLTEXT)
  • BTREE索引(一種將索引值按必定的算法,存入一個樹形的數據結構中)
    MyISAM表數據文件和索引文件是分離的,索引文件僅保存數據記錄的磁盤地址
    InnoDB表數據文件自己就是主索引,葉節點data域保存了完整的數據記錄
    • B-TREE索引

    • B+TREE索引

    B+Tree相對於B-Tree有幾點不一樣:
    非葉子節點只存儲鍵值信息。
    全部葉子節點之間都有一個鏈指針。
    數據記錄都存放在葉子節點中。數據結構

  • HASH索引工具

    • 僅支持"=","IN"和"<=>"精確查詢,不能使用範圍查詢:
      因爲Hash索引比較的是進行Hash運算以後的Hash值,因此它只能用於等值的過濾,不能用於基於範圍的過濾,由於通過相應的Hash算法處理以後的Hash
    • 不支持排序:
      因爲Hash索引中存放的是通過Hash計算以後的Hash值,並且Hash值的大小關係並不必定和Hash運算前的鍵值徹底同樣,因此數據庫沒法利用索引的數據來避免任何排序運算
    • 在任什麼時候候都不能避免表掃描:
      因爲Hash索引比較的是進行Hash運算以後的Hash值,因此即便取知足某個Hash鍵值的數據的記錄條數,也沒法從Hash索引中直接完成查詢,仍是要經過訪問表中的實際數據進行相應的比較,並獲得相應的結果
    • 檢索效率高:
      索引的檢索能夠一次定位,不像B-Tree索引須要從根節點到枝節點,最後才能訪問到頁節點這樣屢次的IO訪問,因此Hash索引的查詢效率要遠高於B-Tree索引
    • 只有Memory引擎支持顯式的Hash索引:
      它的Hash是nonunique的,衝突太多時也會影響查找性能。Memory引擎默認的索引類型便是Hash索引,雖然它也支持B-Tree索引
  • R-Tree索引
    R-Tree在MySQL不多使用,僅支持geometry數據類型,支持該類型的存儲引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種。性能

  • FULLTEXT索引
    即爲全文索引,目前只有MyISAM引擎支持。其能夠在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不過目前只有 CHAR、VARCHAR ,TEXT 列上能夠建立全文索引。
    值得一提的是,在數據量較大時候,現將數據放入一個沒有全局索引的表中,而後再用CREATE INDEX建立FULLTEXT索引,要比先爲一張表創建FULLTEXT而後再將數據寫入的速度快不少。
    它的出現是爲了解決WHERE name LIKE 「%word%"這類針對文本的模糊查詢效率較低的問題。mysql索引

總結:

(1)對於BTREE這種Mysql默認的索引方式,具備廣泛的適用性
(2)因爲FULLTEXT對中文支持不是很好,在沒有插件的狀況下,最好不要使用。其實,一些小的博客應用,只須要在數據採集時,爲其創建關鍵字列表,經過關鍵字索引,也是一個不錯的方法,至少我是常常這麼作的。
(3)對於一些搜索引擎級別的應用來講,FULLTEXT一樣不是一個好的處理方法,Mysql的全文索引創建的文件仍是比較大的,並且效率不是很高,即使是使用了中文分詞插件,對中文分詞支持也只是通常。
   真要碰到這種問題,Apache的Lucene或許是你的選擇。
(4)正是由於hash表在處理較小數據量時具備無可比擬的素的優點,因此hash索引很適合作緩存(內存數據庫)。如mysql數據庫的內存版本Memsql,使用量很普遍的緩存工具Mencached,NoSql數據庫redis等,都使用了hash索引這種形式。
   固然,不想學習這些東西的話Mysql的MEMORY引擎也是能夠知足這種需求的。

擴展:

索引不會命中的狀況:

  • 1.索引沒法存儲null值

    a.單列索引沒法儲null值,複合索引沒法儲全爲null的值。
    b.查詢時,採用is null條件時,不能利用到索引,只能全表掃描。
    • 爲何索引列沒法存儲Null值?

      a.索引是有序的。NULL值進入索引時,沒法肯定其應該放在哪裏。(將索引列值進行建樹,其中必然涉及到諸多的比較操做,null 值是不肯定值沒法比較,沒法肯定null出如今索引樹的葉子節點位置。) 
      b.若是須要把空值存入索引,方法有二:其一,把NULL值轉爲一個特定的值,在WHERE中檢索時,用該特定值查找。其二,創建一個複合索引。例如 create index ind_a on table(col1,1);
      經過在複合索引中指定一個非空常量值,而使構成索引的列的組合中,不可能出現全空值。 

  • 不適合鍵值較少的列(重複數據較多的列)

    假如索引列TYPE有5個鍵值,若是有1萬條數據,那麼 WHERE TYPE = 1將訪問表中的2000個數據塊。
    再加上訪問索引塊,一共要訪問大於200個的數據塊。
    若是全表掃描,假設10條數據一個數據塊,那麼只需訪問1000個數據塊,既然全表掃描訪問的數據塊少一些,確定就不會利用索引了。

  • 索引失效的幾種狀況

    1.若是條件中有or,即便其中有條件帶索引也不會使用(這也是爲何儘可能少用or的緣由),要想使用or,又想讓索引生效,只能將or條件中的每一個列都加上索引 2.對於多列索引,不是使用的第一部分,則不會使用索引 3.like查詢以%開頭(例如where code like '%AB'條件是不會走索引的,而where code like 'AB%'條件是會走索引的) 4.若是列類型是字符串,那必定要在條件中將數據使用引號引用起來,不然不使用索引 5.若是mysql估計使用全表掃描要比使用索引快,則不使用索引

相關文章
相關標籤/搜索