mysql的where、order by和limit的隱藏優化

一、環境準備

mysql InnoDB有下面兩個表:

viewing_number(1814483行數據)
列:id、content_id、sel_count、create_time、update_time

viewing_number_copy(1814483行數據)
列:id、content_id、sel_count、create_time、update_time
索引: update_time

二、觀察與分析(第一組,沒有索引)

觀察

explain select id,update_time from viewing_number v where update_time>="2020-05-27 06:30:55" order by id;
在這裏插入圖片描述

explain select id,update_time from viewing_number v where update_time>="2020-05-27 06:30:55" order by id limit 100;
在這裏插入圖片描述

explain select id,update_time from viewing_number v where update_time>="2020-05-27 06:30:55" order by id limit 10000;
在這裏插入圖片描述

分析

可以發現3次執行計劃是一樣的,都是用到了主鍵索引,並且是在where裏用的。但是where條件裏並沒有用到主鍵……,而是order by用到了。這是什麼原理?

這裏mysql有個優化:

  1. 如果where沒有用到索引,order by也沒有用到索引
    先執行where,全表掃描找出符合條件的行,再按照order by在內存中進行排序。
  2. 如果where沒有用到索引,但是order by用到索引了
    先執行order by,掃描用到的索引,再回表判斷where是否符合條件。
  3. 如果在2的情況下,有limit
    則取夠limit條符合條件的行就返回了,並不會掃描完所有索引。

三、觀察與分析(第二組,有索引)

觀察

explain select id,update_time from viewing_number_copy v where update_time>="2020-05-27 06:30:55" order by id;
在這裏插入圖片描述

explain select id,update_time from viewing_number_copy v where update_time>="2020-05-27 06:30:55" order by id limit 100;
在這裏插入圖片描述

explain select id,update_time from viewing_number_copy v where update_time>="2020-05-27 06:30:55" order by id limit 10000;
在這裏插入圖片描述

分析

可以發現1,3次執行計劃是一樣的,2的執行計劃有點特殊。這是什麼原理?

這裏mysql又有個優化:

  1. 如果where有索引,order by也有索引
    默認情況下,先執行where,掃描用到的索引,找出符合條件的行,再按照order by在內存中進行排序。
  2. 但是如果在1的情況下,有limit,並且limit比較小
    則會先執行order by,掃描用到的索引,再回表判斷where是否符合條件。取夠limit條符合條件的行就返回了,並不會掃描完所有索引。

四、總結

對比三、四小節,可以看出:加索引之後,部分情況下,掃描的行數還變多了,並且使用了內存排序。
所以,加索引不是萬能的,不要想當然,要根據實際業務進行分析和測試。

參考

《sql查詢調優之where條件排序字段以及limit使用索引的奧祕》
《sql order by與索引之間的關係(where條件出現字段纔有效)》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章