MySQL索引

索引

索引是幫助MySQL高效獲取數據的數據結構。筆者理解索引相當于一本書的目錄,通過目錄就知道要的資料在哪里,不用一頁一頁查閱找出需要的資料。關鍵字index

索引分類

唯一索引

強調唯一,就是索引值必須唯一,關鍵字unique index。

創建索引:

  1. create unique index 索引名 on 表名(列名);

  2. alter table 表名 add unique index 索引名 (列名);

刪除索引:

  1. drop index 索引名 on 表名;

  2. alter table 表名 drop index 索引名;

主鍵

主鍵就是唯一索引的一種,主鍵要求建表時指定,一般用auto_increatment列,關鍵字是primarykey。

主鍵創建:
creat table test (id int not null primary key auto_increment);

全文索引

InnoDB不支持,Myisam支持性能比較好,一般在 CHAR、VARCHAR 或 TEXT 列上創建。

單列索引與多列索引

索引可以是單列索引也可以是多列索引(也叫復合索引)。按照上面形式創建出來的索引是單列索引,

創建多列索引:
create table test (id int not null primary key auto_increment,uname char

(8) not null default ”,password char(12) not null,INDEX(uname,password))type

=myisam;

注意:INDEX(a, b, c)可以當做a或(a, b)的索引來使用,但和b、c或(b,c)的索引來使用這是一個最左前綴的優化方法,在后面會有詳細的介紹,你只要知道有這樣兩個概念

查看表的索引

命令:show index from 表名

Table:表名

Key_name:什么類型索引(這了是主鍵)

Column_name:索引列的字段名

Cardinality:索引基數,很關鍵的一個參數,平均數值組=索引基數/表總數據行,平均數值組越接近1就越有可能利用索引

Index_type:如果索引是全文索引,則是fulltext,這里是b+tree索引

InnoDB索引實現

B-樹

性質:是一種多路搜索樹(并不是二叉的):

  1. 定義任意非葉子結點最多只有M個兒子;且M>2;

  2. 根結點的兒子數為[2, M];

  3. 除根結點以外的非葉子結點的兒子數為[M/2, M];

  4. 每個結點存放至少M/2-1(取上整)和至多M-1個關鍵字;(至少2個關鍵字)

  5. 非葉子結點的關鍵字個數=指向兒子的指針個數-1;

  6. 所有葉子結點位于同一層;
    搜索:從根結點開始,對結點內的關鍵字(有序)序列進行二分查找,如果命中則結束,否則進入查詢關鍵字所屬范圍的兒子結點;重復,直到所對應的兒子指針為空,或已經是葉子結點;


    B-樹 M=3

B+樹

性質:B+樹是B-樹的變體,也是一種多路搜索樹:

  1. 其定義基本與B-樹同,除了:

  2. 非葉子結點的子樹指針與關鍵字個數相同;

  3. 非葉子結點的子樹指針P[i],指向關鍵字值屬于[K[i], K[i+1])的子樹(B-樹是開區間);

  4. 為所有葉子結點增加一個鏈指針;

  5. 所有關鍵字都在葉子結點出現;


    B+樹 M=3

綜上所述,用B-Tree作為索引結構效率是非常高的。

為什么使用B+樹

為什么使用B-/+樹

  1. 文件很大,不可能全部存儲在內存中,故要存儲到磁盤上。

  2. 索引的結構組織要盡量減少查找過程中磁盤I/O的存取次數。

  3. 局部性原理與磁盤預讀,預讀的長度一般為頁(page)的整倍數。

  4. 數據庫系統巧妙利用了磁盤預讀原理,將一個節點的大小設為等于一個頁,這樣每個節點只需要一次I/O就可以完全載入。

為什么使用B+樹

  1. B+樹更適合外部存儲,由于內節點無 data 域,一個結點可以存儲更多的內結點,每個節點能索引的范圍更大更精確,也意味著 B+樹單次磁盤IO的信息量大于B-樹,I/O效率更高。

  2. Mysql是一種關系型數據庫,區間訪問是常見的一種情況,B+樹葉節點增加的鏈指針,加強了區間訪問性,可使用在范圍區間查詢等,而B-樹每個節點 key 和 data 在一起,則無法區間查找。

索引使用的時候注意事項

  • 索引不會包含有NULL值的列(MySQL5.0已經優化)。只要列中包含有NULL值都將不會被包含在MySQL索引中,復合索引中只要有一列含有NULL值,那么這一列對于此復合索引就是無效的。所以我們在數據庫設計時不要讓字段的默認值為NULL。

  • 使用短索引。對串列進行索引,如果可能應該指定一個前綴長度。例如,如果有一個CHAR(255)的列,如果在前10個或20個字符內,多數值是惟一的,那么就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省磁盤空間和I/O操作。

  • 索引列排序(單獨order by 用不了索引,索引考慮加where 或加limit) 。MySQL查詢只使用一個索引,因此如果where子句中已經使用了索引的話,那么order by中的列是不會使用索引的。

  • like語句操作 。一般情況下不鼓勵使用like操作,如果非使用不可,如何使用也是一個問題。like “%aaa%” 不會使用MySQL索引而like “aaa%”可以使用索引。

  • OR 其中有一個不是索引會遍歷全表

  • 最左前綴匹配原則,非常重要的原則,mysql會一直向右匹配直到遇到范圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。

  • =和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式。

  • 盡量選擇區分度高的列作為索引,區分度的公式是count(distinct col)/count(*),表示字段不重復的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別字段可能在大數據面前區分度就是0,那可能有人會問,這個比例有什么經驗值嗎?使用場景不同,這個值也很難確定,一般需要join的字段我們都要求是0.1以上,即平均1條掃描10條記錄。

  • 索引列不能參與計算,保持列“干凈”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,需要把所有元素都應用函數才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(’2014-05-29’)。

  • 盡量的擴展索引,不要新建索引。比如表中已經有a的索引,現在要加(a,b)的索引,那么只需要修改原來的索引即可

索引使用的時候注意事項

  • NULL 其實并不是空值,而是要占用空間,建議使用 NOT NULL 而不是 NULL
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容