mysql 查詢優化案例計算

2021-10-02 03:02:34 字數 1953 閱讀 6053

有表takeout_goods,id是自增主鍵,shop_id是普通b+樹索引,其他欄位本案例用不著

語句如下:

語句1:explain select * from takeout_goods where shop_id = 『7691005』

對於這條語句,查詢優化器有兩種走法,一種是去主鍵索引走全表掃瞄,另一種是走shop_id這個輔助索引,找到主鍵id集合後再走主鍵索引查出記錄

語句2:explain select shop_id from takeout_goods where shop_id = 『7691005』

語句2是為了讓他利用覆蓋索引,不用回表

row_evaluate_cost:判讀該行符合條件的代價,cpu代價

io_block_read_cost:磁碟讀取一頁的代價,io代價

查詢成本 = 行數 * row_evaluate_cost+頁數 * io_block_read_cost

row_evaluate_cost和io_block_read_cost這兩個值很多人說是0.2和1,其實不然,各個版本可能不同,具體需要我們查mysql這個庫的server_cost表和engine_cost表得知,如下圖

這上面一切都是我自己的見解,我沒有看見任何書有說這個,也是因為我用1和0.2去計算和查詢優化器計算的相差甚遠,所以在不經意間看到mysql庫點進去看又不經意間看到了cost表,所以才去研究的,經過計算發現我的理論應該是正確的。我的mysql版本是8.0

row_evaluate_cost=0.1

io_block_read_cost=1

所以公式改為如下

查詢成本 = 行數*0.1 + 頁數 * 1

對於這條語句 explain select * from takeout_goods where shop_id = 『7691005』

show table status like 『takeout_goods』; 顯示rows=560215行,資料大小為148570112b

show variables like 『%innodb_page_size%』 顯示一頁是16kb

行數已得知我們先計算頁數,頁數=148570112/1024/16 = 9068頁

手動計算全表掃瞄成本 = 560215* 0.1 + 9068 * 1 = 65089.5

查詢優化器計算出來的是61346(不會檢視查詢優化器的,請參考上篇部落格查詢優化器)

有一點不一樣,但也正常。

select count(*) from takeout_goods where shop_id = 『7691005』 查一下一共多少行,860行

560215行對應9068頁,那麼860對應的就是860/560215*9068 約等 14頁,這樣計算不太準,因為每一行的資料大小不一樣,但沒關係,不需要太精確

手動計算的走shop_id索引的成本 = 860*0.1 + 14 * 1 = 100

下面看看查詢優化器的成本,一看嚇一跳怎麼是591.34,這誤差就大了,是怎麼回事呢?

原因在於shop_id是輔助索引,100只是走了輔助索引的代價,還需要通過輔助索引查出來的主鍵來回表查出*,這部分的代價沒辦法計算,但是可見這部分代價大致是591.34-100=491.34.

不信的話我們可以執行

explain select shop_id from takeout_goods where shop_id = 『7691005』 讓他走覆蓋索引,不回表,看看此時的代價,我檢視查詢優化器後發現是100.9 ,可以說是我們計算的已經非常精確了

mysql 查詢優化案例彙總

一 簡介 此文章為經歷過的sql案例集合和相關思路 二 案例1 現象 測試環境出現select語句,join2張表多次join,explain結果如下 出現 using where,using join buffer block nested loop 思路分析 bnl 5.6優化,首先就看連線字段...

Mysql查詢語句優化之索引優化案例

sql優化說到底還是索引的優化,建立索引並使之生效.單錶優化 create table student id int 11 not null auto increment,stuname varchar 60 default null,age int 11 default null,varchar ...

mysql優化案例

1 使用join還是子查詢 select from employee left join test on test.id employee.id select employee.select id from test where test.id employee.id t from employee...