解读MySQL 8.0新特性:Skip Scan Range
MySQL從8.0.13版本開始支持一種新的range scan方式,稱為Loose Skip Scan。該特性由Facebook貢獻。我們知道在之前的版本中,如果要使用到索引進行掃描,條件必須滿足索引前綴列,比如索引idx(col1,col2), 如果where條件只包含col2的話,是無法有效的使用idx的, 它需要掃描索引上所有的行,然后再根據col2上的條件過濾。
新的優化可以避免全量索引掃描,而是根據每個col1上的值+col2上的條件,啟動多次range scan。每次range scan根據構建的key值直接在索引上定位,直接忽略了那些不滿足條件的記錄。
示例
下例是從官方文檔上摘取的例子:
也可以從optimizer trace里看到如何選擇的skip scan:
我們從innodb的角度來看看這個SQL是如何執行的,我們知道每個index scan都會走到ha_innobase::index_read來構建search tuple,上述查詢的執行步驟:
- 第一次從Index left side開始scan
- 第二次使用key(1,40) 掃描index,直到第一個range結束
- 使用key(1), find_flag =HA_READ_AFTER_KEY, 找到下一個Key值2
- 使用key(2,40),掃描Index, 直到range結束
- 使用Key(2),去找大于2的key值,上例中沒有,因此結束掃描
代碼注入了日志,打印search_tuple(dtuple_print())
從上述描述可以看到使用skip-scan的方式避免了全索引掃描,從而提升了性能,尤其是在索引前綴列區分度比較低的時候
條件
skip scan可以通過Hint或者optimizer_switch來控制(skip_scan),默認是打開的。根據worklog的描述,對于如下query:
需要滿足如下條件才能使用skip scan:
ref: get_best_skip_scan()
當skip scan擁有更低的cost時,會被選擇,計算cost的函數是cost_skip_scan(),由于索引統計信息中已經基于不同的前綴列值估算了distinct value的個數(rec_per_key), 可以基于此去預估可能需要讀的行數。 更具體的可以參考wl#11322中的描述,筆者對此不甚了解,故不做筆墨ref: cost_skip_scan()
總結
以上是生活随笔為你收集整理的解读MySQL 8.0新特性:Skip Scan Range的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里云:面向5G时代的物联网无线连接服务
- 下一篇: Netty原理架构解析