MySQL【十】認識索引

MySQL認識索引

 

什麼是索引?

索引在MySQL中也叫是一種「鍵」,是存儲引擎用於快速找到記錄的一種數據結構。索引對於良好的性能
很是關鍵,尤爲是當表中的數據量愈來愈大時,索引對於性能的影響愈發重要。
索引優化應該是對查詢性能優化最有效的手段了。索引可以輕易將查詢性能提升好幾個數量級。
索引至關於字典的音序表,若是要查某個字,若是不使用音序表,則須要從幾百頁中逐頁去查。html

索引的原理

索引原理

索引的目的在於提升查詢效率,與咱們查閱圖書所用的目錄是一個道理:先定位到章,而後定位到該章下的一個小節,而後找到頁數。類似的例子還有:查字典,查火車車次,飛機航班等mysql

本質都是:經過不斷地縮小想要獲取數據的範圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件,也就是說,有了這種索引機制,咱們能夠老是用同一種查找方式來鎖定數據。算法

數據庫也是同樣,但顯然要複雜的多,由於不只面臨着等值查詢,還有範圍查詢(>、<、between、in)、模糊查詢(like)、並集查詢(or)等等。數據庫應該選擇怎麼樣的方式來應對全部的問題呢?咱們回想字典的例子,能不能把數據分紅段,而後分段查詢呢?最簡單的若是1000條數據,1到100分紅第一段,101到200分紅第二段,201到300分紅第三段......這樣查第250條數據,只要找第三段就能夠了,一會兒去除了90%的無效數據。但若是是1千萬的記錄呢,分紅幾段比較好?稍有算法基礎的同窗會想到搜索樹,其平均複雜度是lgN,具備不錯的查詢性能。但這裏咱們忽略了一個關鍵的問題,複雜度模型是基於每次相同的操做成原本考慮的。而數據庫實現比較複雜,一方面數據是保存在磁盤上的,另一方面爲了提升性能,每次又能夠把部分數據讀入內存來計算,由於咱們知道訪問磁盤的成本大概是訪問內存的十萬倍左右,因此簡單的搜索樹難以知足複雜的應用場景。sql

磁盤IO與預讀

前面提到了訪問磁盤,那麼這裏先簡單介紹一下磁盤IO和預讀,磁盤讀取數據靠的是機械運動,每次讀取數據花費的時間能夠分爲尋道時間、旋轉延遲、傳輸時間三個部分,尋道時間指的是磁臂移動到指定磁道所須要的時間,主流磁盤通常在5ms如下;旋轉延遲就是咱們常常據說的磁盤轉速,好比一個磁盤7200轉,表示每分鐘能轉7200次,也就是說1秒鐘能轉120次,旋轉延遲就是1/120/2 = 4.17ms;傳輸時間指的是從磁盤讀出或將數據寫入磁盤的時間,通常在零點幾毫秒,相對於前兩個時間能夠忽略不計。那麼訪問一次磁盤的時間,即一次磁盤IO的時間約等於5+4.17 = 9ms左右,聽起來還挺不錯的,但要知道一臺500 -MIPS(Million Instructions Per Second)的機器每秒能夠執行5億條指令,由於指令依靠的是電的性質,換句話說執行一次IO的時間能夠執行約450萬條指令,數據庫動輒十萬百萬乃至千萬級數據,每次9毫秒的時間,顯然是個災難。下圖是計算機硬件延遲的對比圖,供你們參考:數據庫

考慮到磁盤IO是很是高昂的操做,計算機操做系統作了一些優化,當一次IO時,不光把當前磁盤地址的數據,而是把相鄰的數據也都讀取到內存緩衝區內,由於局部預讀性原理告訴咱們,當計算機訪問一個地址的數據的時候,與其相鄰的數據也會很快被訪問到。每一次IO讀取的數據咱們稱之爲一頁(page)。具體一頁有多大數據跟操做系統有關,通常爲4k或8k,也就是咱們讀取一頁內的數據時候,實際上才發生了一次IO,這個理論對於索引的數據結構設計很是有幫助。性能優化

認識key

複製代碼
認識mysql中的key:
    index key    普通索引,可以加速查詢,輔助索引
    unique key   惟一 + 索引,輔助索引
    primary key  惟一 + 非空 + 彙集索引
        主鍵做爲條件的查詢若是可以讓索引生效那麼效率老是更高
    foreign key  自己沒有索引的,可是它關聯的外表中的字段是unique索引
    primary key 和unique 標識的字段不須要再添加索引
        直接就能夠利用索引加速查詢
    能用unique的時候儘可能不用index
        unique除了是索引以外還能作惟一約束,若是作了惟一約束
        b+樹就更健康
複製代碼
複製代碼
索引 : 實際上就是一個搜索表時使用的目錄
    彙集索引 : 葉子節點內直接存儲行內容
        只有innodb存儲引擎纔有彙集索引
        主鍵
    輔助索引 : 葉子節點中的數字指向數據的具體地址
        innodb中和myisam中均可以存在
innodb 對應2個文件 表結構 數據 + 索引
myisam 對應3個文件 表結構 純數據 輔助索
複製代碼

彙集索引和輔助索引

複製代碼
id name gender age
1 alex male 18
primary key   index 
彙集索引      輔助索引

建立普通索引
create index 索引名 on 表名(字段名)
desc 表名;
+--------+-----------------------+------+-----+---------+----------------+
| Field  | Type                  | Null | Key | Default | Extra          |
+--------+-----------------------+------+-----+---------+----------------+
| id     | int(11)               | NO   | PRI | NULL    | auto_increment |
| name   | varchar(20)           | YES  |     | NULL    |                |
| sex    | enum('male','female') | NO   |     | male    |                |
| age    | int(11)               | YES  | MUL | NULL    |                |
| dep_id | int(11)               | YES  |     | NULL    |                |
+--------+-----------------------+------+-----+---------+----------------+
show create table 表名;
| employee | CREATE TABLE `employee` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `sex` enum('male','female') NOT NULL DEFAULT 'male',
  `age` int(11) DEFAULT NULL,
  `dep_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `ind_age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 |
複製代碼

結論:數據結構

彙集索引:葉子節點直接存儲行內容,健康的樹查詢速度快僅需3次IO;(select * from 表名 where id = 20;),用匯集索引查找內容;post

輔助索引:葉子節點中的數字指向數據的內存地址,咱們經過用輔助索引查找到數據的內存地址後須要回表到彙集索引,拿着數據的內存地址找到真實的數據,須要6次IO;性能

注意:若是咱們在建立表結構的時候沒有建立主鍵(彙集索引),那麼mysql會自動的幫咱們建立一個主鍵,這個主鍵咱們是看不到的,由於只有主鍵纔是彙集索引,那麼咱們之後查詢表中的數據都是經過輔助索引查詢的,由於輔助索引比彙集索引遇到的IO多,查詢速度更慢些,因此通常咱們在建立表結構的時候都是自定義主鍵,這樣能更好的利用匯集索引的優點;大數據

相關文章
相關標籤/搜索