10 mysql選錯索引

2022-05-01 11:27:12 字數 3230 閱讀 1499

在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

procedure

idata_t11()

begin

declare i int;

set i=1;

while(i<=

100000

)do

insert

into t10 values

(i, i, i);

set i=i+1;

endwhile

;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

and20000; /*

q1*/

select

*from t force index(a) where a between

10000

and20000;/*

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

1and

1000) and (b between

50000

and100000) order

by b limit 1;

一種方法是,採用force index(t)

強行選擇乙個索引。

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

。之前優化器選擇使用索引b,因為它認為使用索引

b可以避免排序(

b本身是索引,已經是有序的,如果選擇索引

b的話,不需要在做排序只需要遍歷),所以即使掃瞄行數更多,也判定為代價更小。

現在使用了 order by b,a,要求按照

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

a索引。

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

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

mysql索引選錯 10 mysql選錯索引

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

10 MySQL入門小結

1.連線操作和集合操作 續 由於mysql不支援full join,我麼可以這樣實現 select from a left join b on a.id b.id union select from a right join b on a.id b.id a.先查出左聯接 b.查出右聯接 c.用un...

10 mysql其它常用

1 檢視 開發中不常用 給某個常用的查詢語句設定別名,方便使用 建立 create view 檢視名稱 as sql 修改 alter view 檢視名稱 as sql 刪除 drop view 檢視名稱 檢視是虛擬的而非物理表。2 觸發器 開發中不常用 執行增刪改語句,自動執行設定的關聯語句 觸發...