MySQL系列(三)---索引
前言:若是有疏忽或理解不當的地方,請指正。有關於數據結構的內容本文沒有詳細介紹,後續會在數據結構系列進行介紹。html
目錄
什麼是索引
- 若是沒有索引,掃描的記錄數大於有索引的記錄數
- 索引存放索引列的值(好比id爲索引列,那麼存放索引列的值),和該索引值對應的行在內存中的地址(或者直接存儲該行的數據)
- SELECT * FROM user WHERE username= 'jiajun' ,username創建索引,若是索引採用的數據結構是hash表,那麼這個時候,經過計算jiajun的hash值,O(1)複雜度就能夠找到該記錄的位置
hash索引
- 在等值查找下,此時無hash衝突,這種狀況下,效率是很高的
- 可是在範圍查找下,因爲hash不是有序的,那麼範圍查找下,hash表的優點並不能發揮出來。
- 在hash衝突下,查找效率會降下來
磁盤讀取
- 磁盤讀取步驟:定柱面,定磁道,定磁塊
- 磁盤時間主要消耗在定位柱面,那麼若是要提升速度,在數據量同樣的狀況下,將盡可能多的數據放在磁盤塊上,那麼這樣能夠減小磁頭定位柱面移動的次數,減小IO的次數。
二叉查找樹
- 左子樹全部的節點的值小於他的根節點的值
- 右子樹全部的節點的值大於他的根節點的值
- 任意節點的左子樹和右子樹都是二叉查找樹
- 沒有鍵值相等的節點
分析
- 二叉查找樹的查找的複雜度到了lgn
- 可是有沒有辦法減小IO的次數,也就是能不能下降樹的高度
B-樹
(m階樹 m/2<=k<=m)mysql
- 根節點至少兩個子節點
- 全部葉子節點都在同一層
- 中間節點包含k-1個元素和k個孩子
- 節點中的元素從小到大排列
- 每一個節點即包含索引列的值,和該數據記錄(或該數據記錄的值)
分析
- 相對於二叉查找樹,B樹變得矮胖,由於每一個節點存放的元素更多,因此相同元素狀況下,下降了樹的高度,那麼就能夠減小IO的次數
- 每一個節點存放了數據(該行記錄的值或者該行記錄在內存的地址),因此不一樣的查詢性能是不同的。
B+樹
- 在B-樹的基礎上
- 除了葉子結點,其餘節點不包含記錄(數據庫中的行)的位置
- 葉子節點包含了全部的索引值,而且從小到大排列,以及記錄(數據庫中行)的位置
分析
- 若是節點的大小同樣,那麼若是咱們除了葉節點以外,其餘節點不包含數據,那麼就能夠放更多的元素(索引值),這樣的話這棵樹就變的更加矮胖,那麼IO的次數能夠進一步減小
- 由於葉節點的元素是順序排列,並且葉節點間造成鏈表,那麼有序查找時提升範圍查詢的效率
- 相對於B樹,因爲全部的數據是存放在葉節點,那麼意味着每次查找都必須到從根查找到葉節點,那麼這就意味着查詢性能平均。
總結
- 索引是一種數據,能夠避免了全表查詢,能夠類比目錄和書。
- 索引須要一種數據結構來存儲
- 利用散列表(hash)的方式查詢複雜度能夠到O(1),可是再範圍查詢時,hash起不了提升性能的做用
- IO操做是耗時,爲了提升查詢性能,能夠減小IO的次數
- 對於樹的存儲結構來講,爲了提升性能,減小IO的次數,能夠低樹的高度
- 讀取一個節點一次IO,在數據量同樣的狀況下,若是每一個節點的能存放更多元素,那麼就能夠下降樹的高度。
- B樹下降了樹的高度,而在節點大小同樣的狀況下,由於B樹的節點存放了元素有又存放了數據,而B+樹將數據所有存放在葉節點,那麼這樣的話,每一個節點能夠存放更多的元素,那麼就能夠再一次下降樹的高度
- B+樹的查詢性能更加穩定,而且更有利於範圍查找
- 若是是彙集索引(InnoDB引擎),那麼節點存放的該記錄的數據,數據文件自己就是索引文件
- 若是是非彙集索引(MyISAM引擎),那麼節點存放的是該行記錄的地址。索引文件和數據文件是分離
索引的種類
- 普通索引,容許出現相同的內容
- 惟一索引,索引值惟一,容許空值
- 主鍵索引,建立主鍵的時候自動建立主鍵索引,惟一而且不能爲空
- 組合索引,多列組合索引
彙集索引和非彙集索引
- 彙集索引指的是索引和數據文件在一塊兒,在InnoDB引擎中,數據文件自己就是索引文件,這個索引的key是主鍵。InnoDB必需要主鍵,若是沒有顯式指定,則MySQL系統會自動選擇一個能夠惟一標識數據記錄的列做爲主鍵,若是不存在這種列,則MySQL自動爲InnoDB表生成一個隱含字段做爲主鍵,這個字段長度爲6個字節,類型爲長整形。
- 非彙集索引指的是索引文件和數據文件分開。在MyISAM中,B+樹中葉節點存放的記錄的地址。而在InnoDB中,非主鍵索引的B+樹中存放的是該記錄主鍵值。
索引的使用
- ALTER TABLE table_name ADD INDEX index_name (column_list) 增長普通索引
- ALTER TABLE table_name ADD UNIQUE (column_list) 增長惟一索引
- ALTER TABLE table_name ADD PRIMARY KEY (column_list) 增長主鍵索引
注意點
- 若是此時爲 username,age,sex建聯合索引
- 最左匹配指優先匹配最左索引,(username)(username,age)(username,age,sex),只要查詢條件用到最左邊的列,通常就會使用索引。順序能夠不一樣,好比(age,username),這是查詢優化器的功勞。
- 模糊查詢只有%號不在第一個字符,索引纔可能被使用,好比username like '%jiajun'因此不被採用
- 若是or中有一個條件沒有索引,sql語句不會用到索引,好比usernmae ='jiajun' or pwd='666',此時索引不被採用
- 組合索引中,若是查詢條件不是索引的第一列,索引可能不會被採用,好比此時where age =1
- 若是列是字符型,好比username是字符型並且是索引列,若是此是查詢username=1 ,沒有加引號,那麼這個時候也不會用索引
- 能夠用 show status like 'Handler_read%' 來查看索引使用狀況。
- 建議實踐爲主
索引原則
- 索引應該設計在where後的列,而不是select後的列
- 索引應該建在區分度大的列,好比狀態只有1 和2就不必建索引了
- 對字符串進行索引的時候,應該制定一個前綴長度,好比一個列爲char(200),若是前面幾個字符就要較大區分度,那麼對前幾個字符創建索引就好了,這樣減小了佔用空間,也提升了速度
- 不要建立太多索引,索引會佔空間,並且更新的時候會下降速度,而且若是有過多的索引,Mysql執行計劃的時候,會考慮各個索引,這也會浪費時間
哪些列適合索引
- 常常做爲查詢條件的列
- 常常做爲排序條件的列
- 常常做爲join條件的列
哪些列不適合索引
- 頻繁修改的列,由於數據被修改,索引要相應修改
- 區分度不高的列,好比性別只有兩種
- 不是常常做爲查詢條件,排序條件,鏈接的列
索引優缺點
- 毫無疑問,在使用正確的狀況下,索引能提升查詢速度
- 索引也能提升分組和排序的速度
- 因爲修改刪除添加時,要調維護索引文件,對樹進行調整,因此性能下降了
- 索引文件也是須要佔用空間的
我以爲分享是一種精神,分享是個人樂趣所在,不是說我以爲我講得必定是對的,我講得可能不少是不對的,可是我但願我講的東西是我人生的體驗和思考,是給不少人反思,也許給你一秒鐘、半秒鐘,哪怕說一句話有點道理,引起本身心裏的感觸,這就是我最大的價值。(這是我喜歡的一句話,也是我寫博客的初衷)
做者:jiajun 出處: http://www.cnblogs.com/-new/
本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。若是以爲還有幫助的話,能夠點一下右下角的【推薦】,但願可以持續的爲你們帶來好的技術文章!想跟我一塊兒進步麼?那就【關注】我吧。sql