mysql索引選錯 10 mysql選錯索引

2021-10-22 10:18:36 字數 2514 閱讀 1317

10 mysql選錯索引

在mysql表中可以支援多個索引,有的sql不指定使用哪個索引,由mysql自己來決定,但是有時候mysql選錯了索引,導致執行很慢。

例子create table`t10` (

`id`int(11) not null,

`a`int(11) default null,

`b`int(11) default null,primary key(`id`),key`a` (`a`),key`b` (`b`)

) engine=innodb;

往表中插入10w記錄

過程delimiter ;;create procedureidata_t11()begin

declare i int;set i=1;while(i<=100000)doinsert into t10 values(i, i, i);set i=i+1;end while;end;;

delimiter ;

call idata_t11();

分析sql語句

mysql> select * from t where a between 10000 and 20000;

session a

session b

start transaction with consistent snapshot;

delete from t;

call idata_t11()

explain  select * from t10 where a between 10000 and 20000;

commit;

session b的查詢語句explain  select * from t10 where a between 10000 and 20000;就不會在選擇所有a了,可以通過慢查詢日誌

set long_query_time=0;select * from t where a between 10000 and 20000; /*q1*/

select * from t force index(a) where a between 10000 and 20000;/*q2*/

優化器的邏輯

選擇索引是優化器的工作,而優化器選擇索引的目的,是找到乙個最優的執行方案,並用最小的代價去執行語句。

在資料庫裡面,掃瞄行數是影響執行代價的因素之一,掃瞄的行數越少,意味著訪問磁碟資料的次數越少,消耗的cpu資源越少。

當然,掃瞄行數並不是唯一的判斷標準,優化器還會結合是否使用臨時表、是否排序等因素綜合判斷。

掃瞄行數是怎麼判斷的?

mysql在真正開始語句執行之前,並不能精確地知道滿足這個條件的記錄是多少,只能根據統計資訊來估算記錄數。

這個統計資訊就是索引的」區分度」,顯然,乙個索引上不同的值越多,這個索引的區分度也就越高,而乙個索引上不同的值的個數,稱為」基數」,這個基數越大越好。

mysql取樣統計的方法,取樣統計的時候,innodb缺省會選擇n個資料頁,統計這些頁面上的不同值,得到乙個平均值,然後乘以這個索引的頁面數,就得到了這個索引的基數。

而資料表是會持續更新的,索引統計資訊也不會固定不變,所以,當變更的行數超過1/m的時候,會自動觸發重新做一次索引統計。

在mysql中,有兩種儲存索引統計的方式,可以通過引數innodb_stats_persitent

([email protected]:3306) [test]> show variables like 'innodb_stats_persistent';+-------------------------+-------+

| variable_name | value |

| innodb_stats_persistent | on |

--設定為on,表示統計資訊會持久化到儲存,預設n=20,m=10

--設定為off,表示統計資訊只儲存在記憶體中,預設n=8,m=16

其實索引統計只是乙個輸入,對於乙個具體的語句來說,優化器還要判斷,執行這個語句要掃瞄多少行

統計資訊不準確,使用analyze table t10;

mysql> explain select * from t where (a between 1 and 1000) and (b between 50000 and 100000) order by b limit 1;

索引選擇異常和處理

一種方法是,採用force index(t)強行選擇乙個索引。

第二種方式就是,可以考慮修改語句,引導mysql使用我們期望的索引。

之前優化器選擇使用索引b,因為它認為使用索引b可以避免排序(b本身是索引,已經是有序的,如果選擇索引b的話,不需要在做排序只需要遍歷),所以即使掃瞄行數更多,也判定為代價更小。

現在使用了 order by b,a,要求按照b,a排序,就意味著使用這兩個索引都需要排序,因此掃瞄行數變成了影響決策的主要條件,此時就選擇了a索引。

當然,這種修改並不是通用的優化手段,只是剛好在這個語句有limit 1,如果都有滿足條件的行,要邏輯結果一致才可以這麼修改。

第三種是在有些場景下,我們可以新建乙個更合適的索引,來提供給優化器做選擇,或者刪掉誤用的索引。

10 mysql選錯索引

在mysql表中可以支援多個索引,有的 sql不指定使用哪個索引,由 mysql 自己來決定,但是有時候 mysql 選錯了索引,導致執行很慢。例子create table t10 id int 11 not null a int 11 default null b int 11 default n...

mysql選錯索引的解決

mysql選錯索引的解決 analyze table 表名 1 強制選擇索引 force index eg select from t force index a where a between 10000 and 20000 缺點 這麼寫不優美 如果索引改了名字,這個語句也得改,顯得很麻煩 遷移資...

MYSQL學習筆記之選錯索引

優化器的目的是選擇索引。他會根據自己內部的判斷,從而選擇乙個最優的執行方案。而判斷是乙個因素就是掃瞄行數,越少的掃瞄行數,就說明訪問磁碟的資料次數越少,消耗的cpu資源也就越少。1.掃瞄行數如何判斷 mysql開始執行之前,並不能知道,滿足這個條件的記錄有多少,而只能採用統計的方法,進行預估。這個統...