1. 程式人生 > 其它 >predicate 列儲存索引掃描_高效能Mysql之索引基礎

predicate 列儲存索引掃描_高效能Mysql之索引基礎

技術標籤:predicate 列儲存索引掃描

索引的優點

索引大大減少了伺服器需要掃描的資料量。

索引可以幫助伺服器避免排序和臨時表。

索引可以將隨機I/O變為順序I/O。

Hash索引

僅MEMORY儲存引擎支援Hash索引

雜湊索引是基於雜湊表實現的,對於每一行資料,儲存引擎都會對所有的索引列計算一個雜湊碼。雜湊碼儲存在索引中,同時在雜湊表中儲存指向每個資料行的指標。

建立Hash索引例子如下

c8577a35a8e902d42456e01599f79be4.png

雜湊索引只需要儲存對應的hash值,所以索引結構很緊湊,查詢速度非常快。

Hash衝突的解決

Hash衝突的解決很一般,利用連結串列儲存hash值相同的行指標。

Hash索引的缺點

Hash索引只儲存Hash值和行指標,不儲存欄位值,不能用索引中的值來避免讀取行。

Hash值不是按照索引值順序儲存的,不能排序。

不支援部分索引,Hash索引的Hash值是根據索引列的所有值計算的,比如按照(A,B)建立Hash索引,就不能按照A來索引。

Hash索引只支援比較查詢,=、IN、<=>,不支援範圍比較,比如WHERE price > 100.

當出現Hash衝突的時候,必須要遍歷所有連結串列中的指標,直到匹配為止。

Hash衝突很多的話,一些維護操作的代價會很高。

InnoDB的Hash索引

InnoDB也有一種基於Hash索引的功能,叫做自適應雜湊索引(adaptive hash index),它是在B-tree索引的上層加一層Hash索引,讓B-Tree索引也具備Hash索引的一些優點。

自定義Hash索引

在某些情況下可以自定義一個B-Tree索引和Hash索引相結合的索引,另B-Tree結點的值不是索引列的值,而是索引列值的hash,這樣通常能達到很高的效率。下面是例子。

建立一個表pseudohash

a81f93ed05c02a851cebb57b5a6c61db.png

其中的url_crc是為了建立url的Hash索引而新增的額外的列,利用crc函式建立hash值

,查詢方式如下。

SELECT id FROM pseudohash WHERE url = 'http://www.baidu.com' AND url_crc = CRC32('http://www.baidu.com');
  • 定義觸發器維護url_crc

定義一個觸發器,在新增行和更新行的時候,自動出發更新url_crc的操作。

2539116f4a11a4af76391c87ec5da461.png

需要注意: 不要用SHA1()和MD5() 作為雜湊函式,這兩個函式計算的hash值是很長的字串,會佔用很大的空間,這兩個函式的目標是儘量避免雜湊衝突,但是效能較差。

因為有很大可能會出現Hash衝突,所以在查詢的時候,不能單獨使額外的新增列url_crc去查詢, 比如下面的語句可能無法查到唯一結果。

f475fffccfb3a05b1b93e3dd4c530465.png

所以,想要用這種索引方式提高查詢效率,查詢的時候的WHERE子句必須同時帶上索引列的Hash值和索引列的值。

SELECT id FROM pseudohash WHERE url = 'http://www.baidu.com' AND url_crc = CRC32('http://www.baidu.com');

索引不是最好的解決方案

只有當索引確實能夠幫助我們縮短查詢時間時候,索引才有用。但是對於非常小的表,索引反而沒有直接全表掃描的效率高;對於中大型的表,索引非常有用;對於特大的表,建立索引和維護索引的開銷會隨著表的增大而增大,索引並不能完全解決查詢效能問題,這時就要使用資料庫的分割槽。這裡不討論分割槽。