MySQL8.0-新特性-DescendingIndex
前言
在MySQL8.0之前的版本中,innodb btree索引中的記錄都是嚴格按照的key的順序來儲存的,但有些時候當我們需要倒序掃描時,效率就會很低。為了解決這個問題,從MySQL8.0版本開始支援在索引Key中倒序儲存。你可以按照實際的sql負載來決定如何建立索引,例如你的查詢中有Order by a desc, b asc,就可以建立索引key(a desc, b asc),而在8.0之前的版本中則可能需要代價比較大的filesort來進行, 此外逆序掃描Btree也有額外的開銷,例如掃描時的page切換,page內掃描,都比正序掃描的開銷要大。
本文簡單介紹下用法,並分析下對應的程式碼實現
以下基於當前最新MySQL8.0.13版本
使用
其實對應的語法一直是存在的,只是沒有做具體的實現,直到8.0版本才真正實現,使用也很簡單,在建立索引時,對索引列加asc/desc關鍵字,舉個簡單的例子:
mysql> CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY a_idx(a DESC, b ASC));
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO t1 VALUES(1,1),(2,2),(3,3);
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT b FROM t1 FORCE INDEX(a_idx);
+------+
| b |
+------+
| 3 |
| 2 |
| 1 |
+------+
3 rows in set (0.00 sec)
mysql> SELECT b FROM t1 FORCE INDEX(PRIMARY);
+------+
| b |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
如上例,可以看到指定不同的索引給出的結果順序也是不一樣的。
mysql> EXPLAIN SELECT * FROM t1 ORDER BY a DESC, b;
+----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-------------+
| 1 | SIMPLE | t1 | NULL | index | NULL | a_idx | 9 | NULL | 3 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+-------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
上例中可以看到explain的結果中沒有filesort, 而在之前的版本中對於這樣的sql是需要進行排序的。
優化器在選擇索引時也會考慮到索引列的順序,目前還有些條件限制:
- 由於涉及到資料的儲存,目前只支援InnoDB
- Descending index 無法使用change buffer
- Descneding index不支援fulltext或spatial index, 選擇desc關鍵字會報錯
- GROUP BY不在隱式的保證順序性,只有明確的指定asc/desc,才去確保順序
實現
筆者主要工作是在innodb引擎,對server層不甚瞭解,本文也主要關注innodb的改動。實際上這個特性的改動主要在server層的優化器和執行器,對於innodb來說,儘管資料儲存發生了變化,但改動反而很少。
資料詞典:
索引上的列屬性被持久化到資料詞典表(dd::Index)
dd::fill_dd_indexes_from_keyinfo
dd::fill_dd_index_elements_from_key_parts
key_rec_cmp
:
比較的兩個key不是大小關係,而是在索引上的前後關係,因此需要考慮鍵值列上是asc還是desc的
對於range查詢,在之前的版本中總是min_Key被傳到innodb作為search_tuple來定位btree,但如果是descending index,則需要選擇max_key來作為search tuple (ref: SEL_ARG::get_min_flag(), SEL_ARG::get_max_flag(), SEL_ROOT::store_min_key)
InnoDB record compare:
為了支援這個特性,innodb的改動實際上並不大,大部分程式碼都是沒有變化的,這主要是因為InnoDB使用了統一的比較函式來決定key值位置,索引物件傳遞到底層的比較函式中,以獲取是否存在descending column.
相關函式:
cmp_dtuple_rec_with_match_low
cmp_whole_field
cmp_data
判斷是否是descending index:
dict_index_has_desc(): 這個函式會掃描索引上所有的列,確保沒有desc column, 這個函式看起來有點效率問題,我們可以給dict_index_t加個flag來判斷,無需每次遍歷
參考文件:
1.官方文件
2. wl#1074: Add Descending indexes support
3.MySQL 8.0 Labs – Descending Indexes in MySQL
4.MySQL 8.0: Descending Indexes Can Speed Up Your Queries
5.相關程式碼
相關文章
- MySQL8.0-新特性彙總MySql
- 新特性
- React 新特性React
- 新特性介面
- Hadoop新特性Hadoop
- Java 11新特性Java
- Java 8 新特性Java
- Android 9.0新特性Android
- ES 2024 新特性
- Go 1.13 新特性Go
- Servlet 3.0 新特性Servlet
- MySQL 8.0 新特性MySql
- PHP 7.4 新特性PHP
- IDL 9.1新特性
- Java 8 新特性Java
- .NET 7新特性
- Prometheus 2.21.0 新特性Prometheus
- Java 17新特性Java
- PostgreSQL 13–新特性SQL
- C++新特性C++
- 玩轉iOS開發:iOS 11 新特性《Layout的新特性》iOS
- 【譯】ES2018 新特性:Rest/Spread 特性REST
- C++11新特性(一):語言特性C++
- C++11新特性(三):語言特性C++
- C++11新特性(二):語言特性C++
- HTML5新特性HTML
- Swift 4.1 的新特性Swift
- React16 新特性React
- [譯] Swift 5.0 新特性Swift
- IntelliJ IDEA 2019.1 新特性IntelliJIdea
- Android O 新特性 — NotificationAndroid
- ES的那些新特性
- Redis5.0 新特性Redis
- css3 新特性CSSS3
- ES2023新特性
- ES2022新特性
- php8新特性PHP
- 新特性 Hook 簡述Hook