1. 程式人生 > >mysql使用偽Hash索引提高查詢效能

mysql使用偽Hash索引提高查詢效能

       我們知道 Mysql 預設引擎是 InnoDB 引擎,而 InnoDB 支援的索引型別為 B-tree 型別,如果對資料表有一個根據長字元查詢的sql,使用 B-tree 索引在大資料量的情況下將會導致效能低下,然而 InnoDB 不支援Hash索引,不過我們可以在 B-tree 基礎上建立一個偽雜湊索引。這和真正的雜湊索引不是一回事,因為還是使用 B-Tree 索引進行查詢,但是它使用雜湊值而不是鍵本身進行索引查詢。你需要做的是在查詢的 where 子句中手動指定使用雜湊函式。

       例如我們有一個表需要儲存大量的 URL ,並根據 URL 進行搜尋查詢。如果使用 B-Tree 來儲存URL,儲存的內容就會很大,因為 URL 本身就很長,我們首先看下錶情況(URL 欄位有索引):

       正常情況下會有如下查詢:

       mysql > select id,url from table_name where url = "https://www.baidu.com"

       若刪除原來 URL 列上的索引,而新增一個被索引的 url_crc 列,使用 CRC32 作為雜湊,就可以使用如下的方式進行查詢:

  mysql > select id,url from table_name where url_crc = CRC32("https://www.baidu.com") and url = "https://www.baidu.com"

這樣做的效能會非常高,因為 MySQL 優化器會使用這個選擇性很高而體積很小的基於 url_crc 列的索引來完成查詢。即使有多個記錄有相同的索引值,查詢依然很快,只需要根據雜湊值做快速的整形比較就能找到索引條目,然後一一比較返回對應的行。另一種方式就是對完整的 URL 字串做索引,那樣會非常慢。

       這樣實現的缺陷是需要維護雜湊值。可以手動維護,也可以使用觸發器實現。但是需要注意的是,如果使用這種方式優化的話,切記請勿使用 SHA1() 和 MD5() 作為雜湊函式。因為這個兩個函式計算出來的雜湊值是非常長的字串,會浪費大量空間,比較時也會更慢。SHA1() 和 MD5() 是強加密函式,設計目標是最大限度消除衝突,但這裡並不需要這樣的高的要求。

       如果資料表非常大,CRC32() 會出現大量的雜湊衝突,則可以考慮自己實現一個簡單的64位雜湊函式。這個自定義函式要返回整數,而不是字串,或者在查詢中 處理雜湊衝突 :當使用雜湊索引進行查詢的時候,必須在 where 子句中包含常量值(即上面sql中的  and url = "https://www.baidu.com"),因為一旦雜湊衝突的話,不帶常量值將返回多條結果集,導致查詢無法正常工作。