mysql優化(5) 索引優化

2021-10-10 00:16:36 字數 2942 閱讀 1477

建立合理地索引能夠提公升資料庫的查詢效率,但是如果建立的索引不合理,不僅會降低資料庫的插入、修改、刪除的效率,而且會降低資料庫的查詢效率。其中最主要的是組合索引的建立和優化。

mysql允許在相同的列上建立多個索引,無論索引是否有實際的意義。且索引一旦被建立,就需要mysql單獨維護重複的索引,且mysql優化器在優化查詢的時候也需要對重複的索引重複進行計算,這樣會影響mysql的效能。

重複的索引一般是指在相同的列上安裝相同的順序建立的相同型別的索引。

冗餘的索引一般是因為存在多列索引使部分單列索引的存在沒有了實際意義。如索引(a,b)與索引(a),那麼索引(a)就是冗餘的索引。以為索引(a,b)可以用來當做索引(a)使用。

一般不需要冗餘索引,應該在盡量在已有索引的基礎上進行擴充套件,而不建立新索引。但是有時候為了效能考慮需要建立新索引,如:在整數列上有乙個索引,現在需要增加乙個很長的varchar列來擴充套件所以,如果該索引是某個查詢的覆蓋索引或者它是myisam表且乙個索引下有很多查詢範圍時,擴充套件該索引會是查詢的效率大大降低-----因為新增的索引列是長varchar型別,它會是原有索引變得很大,這時再去遍歷該索引時,就會比原來慢很多。

一般我們會在where子句中使用比較頻繁的列上建立索引,在列值差異比較大的情況下建立索引會使查詢的效率更高。但是有些時候一些列的值比較固定,但查詢中又經常用到該列進行篩選,如狀態(status)、性別(***)、年齡(age)、刪除標識(is_del)等。這類資訊查詢使用的頻率很高,在建立組合索引時,建議將這類列作為組合索引的字首。也許你會覺得,根據過往經驗,在這類選擇性底的列上建立索引效率不高。下面是我們這麼做的理由:

在這類使用頻率很高,特別是像is_del(刪除標識)在幾乎所有的查詢中都會使用的列。

組合索引加上這樣的列並沒有壞處,而對於沒有用到該條件的查詢,也可以用 「 is_del in (0,1)」 來讓mysql選擇該索引。這樣查詢就可以匹配最左字首,並可以盡可能的使用覆蓋索引。當前這樣做僅限於字段值不太多,in () 列表不太長的情況。

上面提到的in() 子句,可以將多個組合索引合併成乙個組合索引。當然這僅限於兩個組合索引相似,使用in() 子句的列的值的範圍有限。如建立組合索引(is_del, ***, name)和 (is_del, set, age)兩個索引中age和name兩個欄位有差異,這時可以將兩個索引合併(is_del, ***,age,name)。根據索引的最左字首原則,而且欄位age的值有限,而name的值差異較大,這裡就需要將age欄位放在前面,在查詢中如果沒有使用age條件時,需要新增" age in (1,2,3....)" 子句。

注意:上面提到的用in子句來合併和使用組合索引的情況,有一定的侷限性。因為沒增加一條in子句,優化器需要做的組合都將以指數形式增加。如果in條件太多,或in的值過多都會降低查詢效能。比如下面的查詢

where name in ('a','b','c','d')

and age in (20,21,22,23)

and *** in (0,1)

這幾個in條件的所有組合為:4*4*2 = 24種,執行計畫需要檢查where子句這24中組合。

範圍條件查詢是指:age>10   、  created_time < 2020-12-1 , 區別於等著查詢:age = 20 、 name = 'zhou' 、color in ('white','blue','black') ,其中in() 條件相當於多個等值查詢。

範圍查詢和多個等值查詢,他們的查詢效率不同: 

以下面的查詢為例:

where color in ('white', 'black','blue')

and created_time > '2020-12-1'

and age between 20 and 30

對於這個查詢,我們可以使用created_time 索引列或者age索引列,但不能同時使用他們。也許這裡你會想到上面「支援多過濾條件」中提到的,使用in() 子句來同時使用兩個索引列。但這裡我們假設兩個範圍列都有無限個可能的值,即不能使用in() 子句代替。這時該怎麼處理?? 遺憾的是,mysql沒有對於這種查詢的優化處理方案。我們只能通過其他業務邏輯途徑來改變其中乙個範圍查詢條件來處理。 

1、找到並修復損壞的表(corruption)

表損壞一般是因為系統崩潰或其他硬體問題、mysql本身缺陷或作業系統的問題導致表損壞和索引損壞。

索引損壞會導致查詢但會錯誤的結果或莫名其妙的主鍵衝突問題,嚴重時可能導致資料庫崩潰。使用 check table  命令通常能找出大多數的表和索引錯誤。使用 repatr table   命令,來修復損壞的表,但是並不是所有的引擎都支援該命令,這時可以考慮手動修改表的儲存引擎。也可以借助一些儲存引擎相關的離線工具, 如 myisamchk;或者將資料匯出乙份再重新匯入,但如果損壞的是行資料而不是索引,這個方法就無效了。

2、減少索引和資料碎片

b-tree索引可能會碎片化,這會降低查詢的效率。碎片化的索引可能會以很差或無序的方式儲存在磁碟上。尤其對於索引覆蓋掃瞄效率影響極大。

表的資料儲存也可能碎片化,表的資料儲存碎片有三種型別:

對於myisam表,這三類碎片化都有可能;innodb表,不會出現短小的行碎片,它會移動短小的行碎片的並重寫到乙個片段中。

消除碎片空間的方法:

optimize table 命令:對於大多數儲存引擎都有效

匯出再匯入資料重新整理資料

對於myisam儲存引擎,通過排序演算法重建索引消除鎖片

對於新版的innodb,可以通過先刪除在建立索引的方式消除索引碎片

通過乙個no-op操作,重建表: alter table table_name engin=engin_name , engin_name為當前表的儲存引擎。這樣雖然看似沒有對錶做任何操作,但可以消除索引碎片。且對於開啟了expand_fast_index_creation引數的percona server,會同步消除表的碎片空間。

(內容摘自《高效能mysql》第5章 建立高效能索引)

mysql 優化 聚集索引 mysql 索引優化

一.聚集索引 clustered index innodb預設依據主鍵列聚集,myisam不使用 特點 b樹每個葉子包含實際資料行,資料按照索引順序地儲存在物理頁上。優點 1.範圍查詢,獲取指定id的全部資料只需從磁碟讀取少量資料頁 如果不使用聚集索引,每條資料可能引起一次磁碟io。2.由於索引和資...

mysql索引優化原則 MySQL 索引優化原則

索引優化原則 1 最左字首匹配原則,聯合索引,mysql會從做向右匹配直到遇到範圍查詢 3 and d 4 如果建立 a,b,c,d 順序的索引,d是用不到索引的,如果建立 a,b,d,c 的索引則都可以用到,a,b,d的順序可以任意調整。2 和in可以亂序,比如a 1 and b 2 and c ...

mysql索引優化原則 MySQL索引優化

mysql官方對索引的定義 索引是幫助mysql高效獲取資料的資料結構。索引是在儲存引擎中實現的,所以每種儲存引擎中的索引都不一樣。如myisam和innodb儲存引擎只支援btree索引 memory和heap儲存引擎可以支援hash和btree索引。這裡僅針對常用的innodb儲存引擎所支援的b...