MySQL索引相關內容

2021-10-02 19:58:16 字數 3384 閱讀 5897

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+樹的查詢效率更加穩定 

由於非終結點並不是最終指向檔案內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查詢必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每乙個資料的查詢效率相當。

3)b+樹的元素遍歷效率高

b樹雖然提高了io效能,但是並沒有解決元素遍歷效率低下的問題,因為遍歷也要乙個乙個的查詢。但是b+樹就不同了,因為葉子節點互相用指標連線,所以只要順著第乙個查詢到的葉子節點,就可以利用指標去遍歷剩下的元素了。而且,在資料庫中基於範圍的查詢是非常頻繁的,也就是元素遍歷操作非常頻繁,所以b+樹這種結構就會大大優於b樹的結構。

聚簇索引與非聚簇索引:

聚簇索引並不是一種單獨的索引型別,而是一種資料儲存方式。術語『聚簇』表示資料行和相鄰的鍵值聚簇的儲存在一起。

按照聚簇索引排列順序,查詢顯示一定範圍資料的時候,由於資料都是緊密相連,資料庫不用從多個資料塊中提取資料,所以節省了大量的io操作。所以,為了充分利用聚簇索引的聚簇的特性,所以innodb表的主鍵列盡量選用有序的順序id,而不建議用無序的id,比如uuid這種。

對於mysql資料庫目前只有innodb資料引擎支援聚簇索引,而myisam並不支援聚簇索引。

由於資料物理儲存排序方式只能有一種,所以每個mysql的表只能有乙個聚簇索引。一般情況下就是該錶的主鍵。mysql中只有聚簇索引真正儲存資料。其他的索引只記錄指向資料的指標(非主鍵索引儲存的資料有另一種說法是儲存資料的主鍵,然後再去主鍵索引查詢。至於到底儲存的是啥,還有待日後研究。確定是,儲存的是主鍵值,要回查聚簇索引才能得到資料),並不儲存實際的資料。

mysql索引分類:

單值索引        即乙個索引只包含單個列,乙個表可以有多個單列索引

唯一索引        索引列的值必須唯一,但允許有空值

主鍵索引        設定為主鍵後資料庫會自動建立索引,innodb為聚簇索引

復合索引        即乙個索引包含多個列

需要建立索引的情況:

主鍵自動建立唯一索引

頻繁作為查詢條件的字段應該建立索引

查詢中排序的字段,排序欄位若通過索引去訪問將大大提高排序速度

查詢中統計或者分組字段

不要建立索引的情況:

表記錄太少

經常增刪改的表或者字段

where條件裡用不到的字段不建立索引

過濾性不好的不適合建索引

單錶查詢索引優化:

全值匹配我最愛:如果where中有多個等值判斷條件,則應該建立這些條件屬性的復合索引,這樣效率最高。

最佳左字首法則:如果索引了多列,要遵守最左字首法則。指的是查詢從索引的最左前列開始並且不跳過索引中的列。

不在索引列上做任何操作(計算、函式、(自動or手動)型別轉換),會導致索引失效而轉向全表掃瞄

儲存引擎不能使用索引中範圍條件右邊的列

mysql 在使用不等於(!= 或者<>)的時候無法使用索引會導致全表掃瞄

is not null 也無法使用索引,但是is null是可以使用索引的

like以萬用字元開頭('%abc...')mysql索引失效會變成全表掃瞄的操作

字串不加單引號索引失效

關聯查詢索引優化:

保證被驅動表的join欄位已經被索引:驅動表是join左邊的表,被驅動表是join右邊的表(忽略right join,因為可以由left join替代)

left join 時,選擇小表作為驅動表,大表作為被驅動表。

inner join 時,mysql會自己幫你把小結果集的表選為驅動表。

子查詢盡量不要放在被驅動表,有可能使用不到索引。(因為子查詢出來的表是乙個不存在的表,無法建立索引)

能夠直接多表關聯的盡量直接關聯,不用子查詢。

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

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

如果查詢沒有過濾條件,比如where子句或者limit等,就不會使用索引,即使有索引的列組合與排序的列組合一模一樣。

如果排序的列組合的順序與索引的順序不同,也會使索引無效,導致using filesort。

如果排序的不同列之間的排序順序不同,比如一列是公升序排序,另一列是降序排列,那麼也會使索引無效,導致using filesort。但是同時是公升序或者降序是可以使用索引的。(其實,這點我是無法理解的,為什麼排序順序不同就無法使用索引,這可能與復合索引的具體實現有關) 

因為復合索引的其中乙個列作為範圍條件的話,後面的列就不在會使用索引,所以當範圍條件和group by 或者 order by  的字段出現二選一時 ,優先觀察條件欄位的過濾數量,如果過濾的資料足夠多,而需要排序的資料並不多時,優先把索引放在範圍欄位上。反之,亦然。

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

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

MySQL鎖相關內容

mysql的表鎖使用 lock table 表名 read write 語句來新增讀鎖或者寫鎖。通過unlock table 語句來釋放所有表鎖。在對錶加了表鎖時,這個連線就不能再操作其他表了 包括讀和寫 簡而言之,就是讀鎖會阻塞寫,但是不會阻塞讀。而寫鎖則會把讀和寫都阻塞。還有一點就是網上都說表鎖...

mongodb基礎索引相關內容

檢視一條集合的索引情況 db.username getindexes name id ns test.username 以username建立索引 db.username.ensureindex 然後再次檢視該集合的索引 發現索引已建立成功 db.username getindexes name i...

ORACLE相關內容

1 em,dbca,netca,netmgr出現亂碼方案 cd oracle home jre lib mv font.properties font.properties.bak mv font.properties.zh font.properties em,dbca,netca,netmgr詳...