《高效能MySQL》讀書筆記之建立高效能的索引

2022-08-18 19:48:10 字數 4120 閱讀 5961

索引是儲存引擎用於快速找到記錄的一種資料結構。索引優化是對查詢效能優化的最有效手段。索引能夠輕易將查詢效能提高幾個數量級。建立乙個最優的索引經常需要重寫查詢。

5.1 索引基礎

在mysql中,儲存引擎首先在索引中找到對應值,然後根據匹配的索引記錄找到對應的資料行。

索引可以包含乙個或多個列的值。如果索引包含多個列,那麼列的順序也十分重要,因為mysql只能高效地使用索引的最左字首列。

5.1.1 索引的型別

索引有很多態別,可以為不同的場景提供更好的效能。在mysql中,索引是在儲存引擎層而不是伺服器層實現的。

b-tree索引:b-tree通常意味著所有的值都是按順序儲存的,並且每乙個葉子頁到根的距離相同。

儲存引擎以不同的方式使用b-tree索引,效能也各有不同,各有優劣。myisam使用字首壓縮技術使得索引更小,但innodb則按照原資料格式進行儲存。myisam索引通過資料的物理位置引用被索引的行,而innodb則根據主鍵引用被索引的行。

b-tree對索引是順序組織儲存的,所以很適合查詢範圍資料。

b-tree索引適用於全鍵值、鍵值範圍或鍵字首查詢。其中鍵字首查詢只適用於根據最左字首的查詢。

可以使用b-tree索引的查詢型別:

全值匹配:指的是和索引中所有的列進行匹配。

匹配最左字首:只使用索引的第一列。

匹配列字首:也可以匹配某一列的開頭部分。

匹配範圍值:也只使用了索引的第一列。

精確匹配某一列並範圍匹配另外一列:即第一列全匹配,第二列範圍匹配。

只訪問索引的查詢:即查詢只需要訪問索引,而無須訪問資料行。

因為索引樹中的節點是有序的,所以除了按值查詢之外,還可以用於查詢中的order by操作。

下面是一些關於b-tree索引的限制:

如果不是按照索引的最左列進行查詢,則無法使用索引。

不能跳過索引中的列。

如果查詢中有某個列的範圍查詢,則其右邊所有列都無法使用索引優化查詢。

所以索引列的順序非常重要,在優化效能的時候,可能需要使用相同的列但順序不同的索引來滿足不同型別的查詢需求。

雜湊索引(hash index): 基於雜湊表實現,只有精確匹配索引所有列的查詢才有效。對於每一行資料,儲存引擎都會對所有的索引列計算乙個雜湊碼(hash code),雜湊碼是乙個較小的值,並且不同鍵值的行計算出的雜湊碼也不一樣。雜湊索引將所有的雜湊碼儲存在索引中,同時在雜湊表中儲存指向每個資料行的指標。

在mysql中,只有memory引擎顯式支援雜湊索引。如果多個列的雜湊值相同,索引會以鍊錶的方式存放多個記錄指標到同乙個雜湊條目中。

因為雜湊索引只需要儲存對應的雜湊值,所以索引的結構十分緊湊,這也讓雜湊索引查詢的速度非常快。

雜湊索引的限制:

雜湊索引只包含雜湊值和行指標,而不儲存字段值,所以不能使用索引中的值來避免讀取行。

雜湊索引無法用於排序。

雜湊索引也不支援部分索引列匹配查詢,因為雜湊索引始終是使用索引列的全部內容計算雜湊值的。例如在資料列 (a,b)上建立雜湊索引,如果查詢只有資料列a,則無法使用該索引。

雜湊索引只支援等值比較查詢,包括 =, in(), <=>(注意<>和<=>是不同的操作)。也不支援任何範圍查詢。

訪問雜湊索引的資料非常快,除非有很多雜湊衝突(不同的索引列卻有相同的雜湊值)。

如果雜湊衝突很多的話,一些索引維護操作的代價也會很高。

因為這些限制,雜湊索引只適用於某些特定的場合。而一旦適合雜湊索引,則它帶來的效能提公升將非常顯著。

建立自定義雜湊索引:如果儲存引擎不支援雜湊索引,則可以建立自定義的雜湊索引。

思路很簡單:在b-tree上建立乙個偽雜湊索引。這和真正的雜湊索引不是一回事,因為還是使用b-tree進行查詢,但是它使用雜湊值而不是鍵本身進行索引查詢。需要做的就是在查詢的where子句中手動指定使用雜湊函式,可以使用crc32做雜湊,不要使用sha1()和md5()作為雜湊函式(因為這兩個函式計算出來的雜湊值是非常長的字串,會浪費大量空間,比較時也會比較慢)。

如果資料表非常大,crc32()會出現大量的雜湊衝突(當索引有93000條記錄時出現衝突的概率是1%),則可以考慮自己實現乙個簡單的64位雜湊函式,對這個函式的要求是返回整數。乙個簡單的辦法是可以使用md5()函式返回值的一部分作為自定義雜湊函式,還可以使用如fnv64()函式作為雜湊函式,這是移植自percona server 的函式,可以以外掛程式的方式在任何mysql版本中使用,生成的雜湊值是64位,速度快,且衝突比crc32()要少得多。

處理雜湊衝突:當使用雜湊索引進行查詢時,必須在where子句中包含常量值,例如:

mysql>select id from url where url_ctc = crc32("") and url="";

5.2 索引的優點

最常見的b-tree索引,按照順序儲存資料,所以mysql可以用來做order by和group by操作。因為資料是有序的,所以b-tree也就會將相關的列值都儲存在一起。最後,因為索引中儲存了實際列的值,所以某些查詢只使用索引就能夠完成全部查詢。

三大優點:

1. 索引大大減少了伺服器需要掃瞄的資料量

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

3. 索引可以將隨機i/o變為順序i/o

總的來說,只有當索引幫助儲存引擎快速地找到記錄帶來的好處大於其帶來的額外工作時,索引才是有效的。對於非常小的表,大部分情況下簡單的全表掃瞄更高效。對於中到大型的表,索引就非常有效。但對於特大型的表,建立和使用索引的代價將隨之增長。

5.3 高效能的索引策略

5.3.1 獨立的列

如果查詢中的列不是獨立的,則mysql就不會使用索引。「獨立的列」是指索引的列不能是表示式的一部分,也不是函式的引數。

mysql>select actor_id from sakila.actor where actor_id + 1 =5;

mysql>select ... where to_days(current_date) - to_day(date_col) <= 10;

5.3.2 字首索引和索引選擇性

有時候需要索引很長的字元列,這會讓索引變得大且慢。乙個策略是前面提到過的模擬雜湊索引。但有時候這樣做還不夠,通常可以索引開始的部分字元,這樣可以大大節約索引空間,從而提高索引效率,但這樣會降低索引的選擇性。索引的選擇性是指,不重複的索引值(也稱為基數,cardinality)和資料表的記錄總數(#t)的比值,範圍從1/#t到1之間。索引的選擇性越高則查詢效率越高。唯一索引的選擇性是1,這是最好的索引選擇性,效能是最好的。

5.3.3 多列索引

乙個常見錯誤就是,為每個列建立獨立索引,或者按照錯誤的順序建立多列索引。

在多個列上建立索引大部分情況下並不能提高mysql的查詢效能。

例如,表film_actor在字段film_id和actor_id上各有乙個單列索引。但對於下面的查詢,這兩個單列索引都不是好的選擇:

mysql>select film_id,actor_id from sakila.film_actor

->where actor_id = 1 or film_id = 1;

在mysql 5.0 和更新的版本中,查詢能同時使用這兩個單列索引進行掃瞄,並將結果進行合併。這種演算法有三個變種:or條件的聯合(union),and條件的相交(intersection),組合前兩種情況的聯合和相交。通過explain中的extra可以看到這一點:

mysql>explain select film_id,actor_id from sakila.film_actor

->where actor_id = 1 or film_id = 1\g;

********************1. row****************************

......

extra: using union(primary,idx_fk_film_id),using where

索引合併策略有時候是一種優化的結果,但實際上更多時候說明表上的索引建得很糟糕。

當出現伺服器對多個索引做相交操作時(通常有多個and條件),通常意味著需要乙個包含所有相關列的多列索引,而不是多個獨立的單列索引。

當伺服器需要多個索引做聯合操作時(通常有多個or操作),通常需要耗費大量的cpu和記憶體資源在演算法的快取、排序和合併操作上。

(未完待續)

如果您覺得閱讀本文對您有幫助,歡迎**本文,但是**文章之後必須在文章頁面明顯位置保留此段宣告,否則保留追究法律責任的權利。

作  者:www.jpdou.top

高效能MySQL 讀書筆記

第4章 schema與資料型別優化 第5章 建立高效能的索引 三星索引 最左匹配原則 高效能索引策略 多列索引 mysql採用的是分層架構 上層是server層,下層是儲存引擎層。sql標準中定義了四種隔離級別 隔離級別 定義髒讀 不可重複讀 幻讀加鎖讀 讀未提交 read uncommitted,...

高效能Mysql 讀書筆記

mysql與眾不同的特性是它的儲存引擎架構,這種架構將查詢處理即其他的任務系統和資料的儲存 提取相分離.第二層架構中,大多數的mysql的核心服務功能都在這一層,包括查詢解析,分析優化,快取以及所處的內建函式,所有的跨儲存引擎的功能都在這一層實現 儲存過程,觸發器,檢視等.第三層包含mysql的儲存...

高效能mysql讀書筆記1

譯者序言 本書的定位 系統的從各個方面講述乙個高效能mysq應用應該怎麼做,區別於市面上那些關於mysql開發書籍只是停留在學習mysql基本語句,本書提供了作者一些mysql調優的基準測試從而幫助理解mysql內部的工作機制,本書強調mysql的可用性 準確性以及效能。本書根據mysql5.0穩定...