iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0
Software Development

我獨自升級之資料庫從入門到中階系列 第 14

Day14 select 經歷了哪些-執行sql階段

  • 分享至 

  • xImage
  •  

Day14 select 經歷了哪些-執行sql階段

這邊舉一個PK查詢,一個全表掃描為例

  • PK查詢
    select * from product where id = 1;
  1. 比對的欄位是PK,且是等於比對,優化器(前面說的優化階段)選擇了 const 類型的查詢(const是走PK的查詢,速度快,全表掃描是ALL速度慢,可以用 explain 來看)。
  2. 儲存引擎通過B+Tree結構定位到id=1的第一條紀錄,如果紀錄不存在,返回錯誤; 如果紀錄存在,返回紀錄。
  3. 執行器從儲存引擎讀到紀錄,判斷紀錄是否符合查詢條件,符合就回傳給 client。
    大致上是這樣,更細節請參考原文小林coding
  • 全表掃描
    如果是走全表掃描例如
    select * from product where name = 'iphone';
    那就會上述的步驟,把整張表逐一比對。

以下就相對不一定這麼重要,算是MySQL本身的優化,可以有興趣再閱讀

索引下推

| Name  | Age | Reward    |
|-------|-----|-----------|
| 路飛  |  20 | 100000    |
| 索隆  |  22 | 900000    |
| 香吉士 |  24 | 800000    |
| 凱多  |  49 | 19999999  |
| 娜美  |  18 | 50000     |

如果我有一個表如下,做了聯合索引 index(Age, Reward)

select * from t_user where age > 20 and reward = 100000;

因為是範圍查詢(age>20),只有 age 可以利用到聯合索引, reward 無法利用(詳細參考索引常見面試題)。

沒有索引下推(MySQL5.6之前版本)的流程

  1. server層調用儲存引擎功能查到二級索引age>20的第一條紀錄
  2. 拿到這條紀錄的PK(這邊我發現沒有特別介紹,可能再請看的人稍微查一下二級索引的查詢流程),然後進行回表,將整個row回傳給server層。
  3. server層判斷reward=100000 是否為真,成立救回傳給client,不然就跳過這筆紀錄。
  4. 繼續向儲存引擎要下一條紀錄,在二級索引定位到紀錄,拿到PK,回表,回給server,比對條件對還不對。
  5. 反覆上面1~4,直到把紀錄讀完。

沒有索引下推的版本,每查到一次二級索引,都會回表

有索引下推的流程

  1. 找到二級索引age>20的第一調紀錄
  2. 先不回表,而是判斷 reward欄位的值是否等於10000,成立回表,不成立跳過。
  3. 回去server層的再判斷其他查詢條件(目前查詢沒有其他條件),成立就回給client,不成立就跳過

結論:有了索引下推,雖然reward欄位沒法使用到聯合索引,但直接在儲存引擎中filter出 reward=10000才執行回表,節省了回表操作,理論上效能更好。
有使用索引下推 在 explain sql 的資訊裡面 Extra欄位 會顯示 Using index condition

明天分享為什麼 MySQL innodb 使用 B+Tree


上一篇
Day13 select語句經歷了哪些
下一篇
Day15 為什麼使用 B+Tree 當作儲存結構
系列文
我獨自升級之資料庫從入門到中階20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言