MySQL索引相關內容

MySQL官方對索引的定義爲:索引(Index)是幫助MySQL高效獲取數據的數據結構。
可以得到索引的本質:索引是數據結構。

索引的優勢:(1)類似大學圖書館建書目索引,提高數據檢索的效率,降低數據庫的IO成本;(2)通過索引列對數據進行排序,降低數據排序的成本,降低了CPU的消耗。

索引的劣勢:(1)雖然索引大大提高了查詢速度,同時卻會降低更新表的速度,如對錶進行INSERT、UPDATE和DELETE。
因爲更新表時,MySQL不僅要保存數據,還要保存一下索引文件每次更新添加了索引列的字段,
都會調整因爲更新所帶來的鍵值變化後的索引信息;(2)實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,所以索引列也是要佔用空間的。

MySQL的索引所使用的數據結構是B+樹,而不是B樹。B-樹的關鍵字和記錄是放在一起的,葉子節點可以看作外部節點,不包含任何信息;B+樹的非葉子節點中只有關鍵字和指向下一個節點的索引,記錄只放在葉子節點中。

選擇B+樹的原因是:在有限的內存下:

                                1) B+樹的磁盤讀寫代價更低 
                                 B+樹的內部結點並沒有指向關鍵字具體信息的指針。因此其內部結點相對B 樹更小。如果把所有同一內部                                          結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。一次性讀入內存中的需要查找                                          的關鍵字也就越多。相對來說IO讀寫次數也就降低了。 
                                2) B+樹的查詢效率更加穩定 
                                由於非終結點並不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必                                       須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。

 

聚簇索引與非聚簇索引:

聚簇索引並不是一種單獨的索引類型,而是一種數據存儲方式。術語‘聚簇’表示數據行和相鄰的鍵值聚簇的存儲在一起。

按照聚簇索引排列順序,查詢顯示一定範圍數據的時候,由於數據都是緊密相連,數據庫不不用從多個數據塊中提取數據,所以節省了大量的io操作。
對於mysql數據庫目前只有innodb數據引擎支持聚簇索引,而Myisam並不支持聚簇索引。
由於數據物理存儲排序方式只能有一種,所以每個Mysql的表只能有一個聚簇索引。一般情況下就是該表的主鍵。
爲了充分利用聚簇索引的聚簇的特性,所以innodb表的主鍵列儘量選用有序的順序id,而不建議用無序的id,比如uuid這種。

MySQL索引分類:

  1. 單值索引        即一個索引只包含單個列,一個表可以有多個單列索引
  2. 唯一索引        索引列的值必須唯一,但允許有空值
  3. 主鍵索引        設定爲主鍵後數據庫會自動建立索引,innodb爲聚簇索引
  4. 複合索引        即一個索引包含多個列

需要創建索引的情況:

  1. 主鍵自動建立唯一索引
  2. 頻繁作爲查詢條件的字段應該創建索引
  3. 查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度
  4. 查詢中統計或者分組字段

不要創建索引的情況:

  1. 表記錄太少
  2. 經常增刪改的表或者字段
  3. Where條件裏用不到的字段不創建索引
  4. 過濾性不好的不適合建索引

單表查詢索引優化:

  1. 全值匹配我最愛:如果where中有多個等值判斷條件,則應該創建這些條件屬性的複合索引,這樣效率最高。
  2. 最佳左前綴法則:如果索引了多列,要遵守最左前綴法則。指的是查詢從索引的最左前列開始並且不跳過索引中的列。
  3. 不在索引列上做任何操作(計算、函數、(自動or手動)類型轉換),會導致索引失效而轉向全表掃描
  4. 存儲引擎不能使用索引中範圍條件右邊的列
  5. mysql 在使用不等於(!= 或者<>)的時候無法使用索引會導致全表掃描
  6. is not null 也無法使用索引,但是is null是可以使用索引的
  7. like以通配符開頭('%abc...')mysql索引失效會變成全表掃描的操作
  8. 字符串不加單引號索引失效

關聯查詢索引優化:

  1. 保證被驅動表的join字段已經被索引:驅動表是join左邊的表,被驅動表是join右邊的表(忽略right join,因爲可以由left join替代)
  2. left join 時,選擇小表作爲驅動表,大表作爲被驅動表。
  3. inner join 時,mysql會自己幫你把小結果集的表選爲驅動表。
  4. 子查詢儘量不要放在被驅動表,有可能使用不到索引。(因爲子查詢出來的表是一個不存在的表,無法創建索引)
  5. 能夠直接多表關聯的儘量直接關聯,不用子查詢。

子查詢索引優化:儘量不要使用not in  或者 not exists,用left outer join ... on  ...  where xxx is null 替代。因爲用not in(子查詢)                                 的話,子查詢出來的結果是一個不存在的表,只能全掃描,無法使用索引。而後面的寫法可以使用索引。

排序查詢索引優化:對於,排序查詢的優化,關鍵就是使用索引現成的排序,而避免出現using filesort。有三條原則:

  1. 如果查詢沒有過濾條件,比如where子句或者limit等,就不會使用索引,即使有索引的列組合與排序的列組合一模一樣。
  2. 如果排序的列組合的順序與索引的順序不同,也會使索引無效,導致using filesort。
  3. 如果排序的不同列之間的排序順序不同,比如一列是升序排序,另一列是降序排列,那麼也會使索引無效,導致using filesort。但是同時是升序或者降序是可以使用索引的。(其實,這點我是無法理解的,爲什麼排序順序不同就無法使用索引,這可能與複合索引的具體實現有關) 
  4. 因爲複合索引的其中一個列作爲範圍條件的話,後面的列就不在會使用索引,所以當範圍條件和group by 或者 order by  的字段出現二選一時 ,優先觀察條件字段的過濾數量,如果過濾的數據足夠多,而需要排序的數據並不多時,優先把索引放在範圍字段上。反之,亦然。

分組查詢索引優化:group by 使用索引的原則幾乎跟order by一致 ,唯一區別是groupby 即使沒有過濾條件用到索引,也可以直接使用索引。(因爲group by 分組就是先排序再分組的)

什麼是覆蓋索引?簡單說就是,select 到 from 之間查詢的列 <=使用的索引列+主鍵。通俗的說就是,你想查詢哪些列,就在select子句中寫明,不要用*代替,這樣做的話,即使在不能使用索引的情況,也能勉強用上一點索引,來提升一點速度。(這點,我也是不理解的,很懵逼。。,爲啥呢?)

                                  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章