SQL中的索引設計規範 三星索引

2021-10-02 05:21:51 字數 2480 閱讀 8343

首先要明確,我們平時所說的最左匹配,針對的是索引中的列的順序,與sql語句where後面跟的條件無關。因為語句中的條件謂詞可以隨意調整順序不影響結果,sql優化器會自動幫我們調整順序以使用索引。在索引匹配時,遇到範圍和模糊匹配時終止。

select name,age,address,phone,email where name =

'mutou_ren'

and address =

'china'

and age >

20and phone like

'132%'

對於以上sql,有索引(address,name,age,phone)

sql經過優化器的調整可以變成如下,不會帶來任何影響(address和name的順序換了一下)

select name,age,address,phone,email where address =

'china'

and name =

'mutou_ren'

and age >

20and phone like

'132%'

在進行所以匹配時,address、name、age均能進行所以匹配,這三個欄位將對本次查詢的索引片進行過濾。

我們假設表有一千萬條記錄,經過以上三個索引欄位的過濾,我們只需要掃瞄1萬行索引記錄。

由於存在字段email不存在索引記錄中,因此在掃瞄這一萬行索引記錄時,會拿到主鍵然後去表記錄中查詢記錄,即所謂的回表,由於拿到的主鍵無法保證連續,因此每次回表都可以看成一次隨機訪問,隨機訪問的成本遠遠大於順序訪問,回表造成的隨機訪問是效能開銷的大頭。

再來看索引(address,name,age,phone),雖然由於age的範圍查詢導致索引中的phone無法參與索引片的過濾,但由於where謂詞中存在phone,在掃瞄索引片然後進行回表查詢時,phone能夠起到過濾的作用,對於不滿足的條件的回表進行過濾,從而減少回表次數。因此即使最左匹配沒有匹配到,但所有出現在where謂詞中的索引字段對於查詢效率都存在著提公升作用

索引(無論聚簇還是輔助)是基於b+樹的(這裡僅針對mysqlinnodb引擎),對於非葉子節點,以目前的硬體來講基本是可以全部放在記憶體中的,我們不考慮這部分的訪問時間,僅對可能放在磁碟上的葉子節點的訪問進行評估。

由於索引是存在順序的,因此在索引掃瞄時,可以看作只有第一條索引的訪問是隨機讀,後面的都是順序讀。而根據輔助索引拿到的主鍵可能是不連續的,因此每次回表都可以看成一次隨機讀。隨機讀的開銷遠遠大於順序讀的開銷(可達千倍)

有了以上的概念,我們可以提出索引中的三星準則,我們按重要程度來講

第三星對於要查詢的所有字段,全都新增到索引中,這裡不考慮順序。

索引中包含全部的要查詢內容,可以完全避免回表查詢,將過濾掉絕大部分的隨機讀訪問,對效能的提公升很明顯。但會導致索引的增大,極端情況與表記錄完全一致

第一星根據where中謂詞,最小化要掃瞄的索引片。將範圍查詢的索引字段放在索引的後面,等值的放在前面。要掃瞄的索引記錄少即代表了可能回表的次數的減少

第二星利用索引的有序性避免排序。對於where a = 1 and b = 1 order by c的語句,索引(a,b,c)中對於a = 1 and b = 1的記錄已經是按照c進行排序了,因此這時查詢可以不需要再進行額外的排序直接返回。

由於目前排序的成本越來越低,在索引設計時,已優先滿足第三星,第一星為準。

對於設計階段的索引設計,可以按照三星標準來設計,對於已經存在的系統進行索引優化時,我們可以參照bq法

在已有的索引上增加where謂詞中的字段,形成索引過濾,儘量減少回表次數,形成半寬索引

對所有的查詢字段新增在已有的索引中,做到0回表,形成寬索引

按照三星準則設計新的索引

如果記錄比較少,全表掃瞄可能會比索引更快。

因為全表掃瞄是順序的,且掃瞄一次即可。而走索引可能會產生回表造成的隨機讀。

mysqlinnodb引擎中,連線查詢走的是迴圈巢狀的方式,即先查出驅動表的符合條件的記錄,然後再根據驅動表的記錄對巢狀表進行掃瞄過濾。

驅動表進行驅動巢狀表時,每一條記錄的驅動我們都可以看做是一次隨機讀操作,因此就有我們平時所說的小表驅動大表的優化準則,如我們常說的inexists哪個效率高?

in是內錶驅動外表,而exists是外表驅動內錶,那個表是驅動表就先查哪個表,因此驅動表記錄越少,造成的隨機讀次數就越少。因此我們可以知道in適合內錶結果集少的情況,而exists恰恰相反。

索引設計規範原則

1 原則上表索引的個數不能超過5個 2 原則上單個欄位上的索引不能超過2個 3 原則上覆合索引引用的字段不能超過3個字段 4 原則上分割槽表的索引型別全部使用local索引 5 配置資料類的表,如資料量比較少,除了主鍵外原則上不建索引 6 介面類和工單類的表,盡可能減少索參數量或者不建索引 7 索引...

MySQL 三星索引

表 test 列 a,b,c,d,e,f 索引 idx a b c a,b,c a列 過濾因子1 b列 過濾因子10 第一顆星,保證最窄的索引片 select a,b,c,d,e,f from test where a a1 and b b1 and c c1 索引idx a b c 滿足了所有的謂...

高效能MySQL中的三星索引

我對此提出了深深的疑問 一星 相關的記錄指的是什麼?相關這個詞很深奧,相關部門 是什麼部門 二星 如果建立了b tree b tree 索引,資料就有序了。三星 索引的列包含了查詢需要所有的列?根本不需要在where查詢條件所有的列上建立索引!我認為一星和二星的rows應該是columns,索引不關...