在平時開發過程中寫sql時,我們通常都不太關心sql的效能,只有能給查出來資料,sql的執行速度不是太慢就不會去管它了。但是開發時期的資料量往往都不是太大,很多效能問題只有在生產環境中才會發現,如:資料過多、sql關聯了太多的表,使用了太多的join、或者建立了索引,但是索引失效的問題。所以要解決這些效能上的難題,就要去研究mysql最為重要的特性--索引。
一、索引的簡介
1.索引的定義
首先我們來看看官網上,對索引的定義:索引(index)是幫助mysql高效獲取資料的資料結構。這種資料結構是btree或b+tree(我們這裡不會去介紹這兩種樹)。
詳細的來講,資料庫維護著兩種東西,乙個是使用者本身儲存的資料,另乙個則是滿足特定查詢演算法的資料結構,資料結構可以通過一些特定的方式來指向我們使用的資料,這樣就可以在這些資料結構的基礎上實現高階查詢演算法,這種資料結構就是索引。
2.索引的特點
索引的優點:
第一點:能夠提高資料庫檢索資料的效率,降低資料庫對磁碟的io讀取次數。
第二點:排序過程中是需要消耗cpu資源的,如果加上了索引,那麼就會降低cpu的消耗。
索引的缺點:
第一點:索引本身也是一種資料,所以建立了索引會減少磁碟的容量。
第二點:在進行新增、更新、刪除過程中,如果新增了索引,mysql還要對索引進行增刪改操作,所以索引對增刪改操作是負面的。
3.索引的分類
a.單值索引
即乙個索引只包含單個列,乙個表可以有多個單列索引
b.唯一索引
索引列的值必須唯一,但允許有空值
c.主鍵索引
設定為主鍵後資料庫會自動建立索引,innodb為聚簇索引
d.復合索引(也叫組合索引)
即乙個索引包含多個列,一般來說復合索引的價效比要比單值索引高的多,因此一般建議在建立索引時優先選擇復合索引。
4.如何建立索引
首先我們來看看哪些欄位要建立索引:
a.主鍵會自動建立唯一索引,
b.查詢中where後面的條件字段應該建立索引,
c.進行連表查詢中,與其他表有外來鍵關係的字段要建立索引,
d.在有排序和分組的查詢中,需要給排序的字段和分組的字段建立索引,
e.對需要統計的字段,應該加上索引。
在上面我們已經說過了,索引雖然能夠大大加快我們的查詢速度,但是它也是有缺點的,針對它的缺點我們來看看那些情況不需要加索引:
a.表中的資料太少不需要加索引,這是因為表記錄太少的話查詢速度本身就會很快,加上索引提公升不大,而且還會多占用磁碟容量。
b.在對錶的操作中,都太多的增刪改情況的字段不加索引。對於這種字段,雖然提供了查詢速度,但是會降低更新表的速度,因為在進行增刪改操作時,mysql也會對索引進行更新。
c.過濾性太低的字段不要加索引。首先我們來看看什麼是過濾性,所謂過濾性指的是這個條件能夠過濾多少條記錄。舉個例子,如user表中的性別(只有男、女性別的情況)字段。
二、查詢優化
1.索引失效
在我們實際開發中,是不是往往會遇到即使加上了索引,sql執行的速度有沒有提高很多,面對這樣的情況,很可能就是索引了,接下來我們就來看看索引失效的規則:
a.最佳左字首法則
定義:如果索引了多列,要遵守最左字首法則。指的是查詢從索引的最左前列開始並且不跳過索引中的列。我們來看乙個例子
先建立一張user表,有三個字段
給這三個字段新增復合索引
然後我們來看乙個sql:
select * from user where name='小明' and userid='1'
我們來分析下這個sql,在where的後面有兩個條件name和userid,首先根據建立的索引,name是能使用的,而userid就不一樣了,在建立的索引中name的後面是age,那麼根據左字首法則,那麼userid沒有用到索引。那麼為什麼索引的使用是必須遵守左字首法則呢,這是和索引建立的資料結構有關,如圖。
根據圖我們可以看到,復合索引的建立是乙個層級關係,每一層都是由上面的字段指向下乙個字段。所以在name_age_userid這個復合索引中,name欄位是指向age欄位的,age是指向userid欄位的,name和userid沒有直接關係,因此回到我們的sql,索引只會命中name欄位,這就是為什麼遵循左字首法則的原因。
b.不在索引列上新增任何操作,如函式、計算、型別轉換
看乙個例子:還是上面的那張表,有兩個sql:
select * from user where userid=1;
select * from user where userid='1'
這兩個sql中有很明顯的是,只有第二個才會用到索引,這是因為我們的userid是varchar型別,而第乙個sql中,where後面的userid是用了乙個數字進行比較,這就會讓這個索引列進行了一次型別轉換,導致了索引失效的問題。
c.儲存引擎不能使用索引中範圍條件右邊的列
看乙個例子:
select * from user where name='小明' and age>17 and userid='1';
這個sql索引失效的問題也比較簡單,首先name能給命中索引,然後age欄位由於是乙個範圍查詢,所以索引不能命中age;最後根據左字首法則,age沒有命中索引的,那麼userid也無法命中。
接下來的幾個索引失效規則都比較簡單,就直接列出來:
d.在使用不等於(!= 或者<>)的時候無法使用索引會導致全表掃瞄。
e.在查詢過程中is not null 也無法使用索引,但是is null是可以使用索引的。
f.在進行模糊查詢過程中,like以萬用字元開頭('%abc...')mysql索引失效會變成全表掃瞄的操作。
2.如何正確建立索引
在介紹了索引失效問題後,我們在以後建立和使用索引時就會有乙個很好的思路,下面我們就來總結一下如何正確的建立索引
a.在建立復合索引中,過濾性越好的字段順序應該越靠前越好。
b.組合索引的建立中,有範圍查詢、不等於、is not null條件的字段應該放在最後。
c.組合索引的字段中,最好包含where後面中所有的索引字段。
e.在使用left join 時,小表作為驅動表(主表),大表作為非驅動表,這樣做能給使索引最大化的利用。
f.子查詢不要用與join的驅動表,因為索引會失效。
mysql怎麼安裝索引 MySQL 索引詳解
6.索引的長度 在為char和varchar型別的資料列定義索引時,可以把索引的長度限制為乙個給定的字元個數 這個數字必須小於這個欄位所允許的最大字元個數 這麼做的好處是可以生成乙個尺寸比較小 檢索速度卻比較快的索引檔案。在絕大多數應用裡,資料庫中的字串資料大都以各種各樣的名字為主,把索引的長度設定...
mysql索引實現 mysql 索引是怎麼實現的?
看了很多關於索引的部落格,講的大同小異。但是始終沒有讓我明白關於索引的一些概念,如b tree索引,hash索引,唯一索引.或許有很多人和我一樣,沒搞清楚概念就開始研究b tree,b tree等結構,導致在面試的時候答非所問!本文中有關儲存引擎請檢視mysql儲存引擎 innodb和myisam ...
mysql怎麼加索引 mysql怎麼新增索引
在mysql中可以通過使用alter table這個sql語句來為表中的字段新增索引。1 新增primary key 主鍵索引 mysql alter table table name add primary key column 2 新增unique 唯一索引 mysql alter table ...