共計 4943 個字符,預計需要花費 13 分鐘才能閱讀完成。
本篇內容主要講解“MYSQL5.6 5.7 處理數據分布不均的問題分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓丸趣 TV 小編來帶大家學習“MYSQL5.6 5.7 處理數據分布不均的問題分析”吧!
處理數據分布不均,orace 數據庫使用額外的統計數據直方圖來完成,而 MYSQL
中統計數據只有索引的不同值這樣一個統計數據,那么我們制出如下數據:
mysql select * from test.testf;
+——+———-+
| id | name |
+——+———-+
| 1 | gaopeng |
| 2 | gaopeng1 |
| 3 | gaopeng1 |
| 4 | gaopeng1 |
| 5 | gaopeng1 |
| 6 | gaopeng1 |
| 7 | gaopeng1 |
| 8 | gaopeng1 |
| 9 | gaopeng1 |
| 10 | gaopeng1 |
+——+———-+
10 rows in set (0.00 sec)
name 上有一個普通二級索引
mysql analyze table test.testf;
+————+———+———-+———-+
| Table | Op | Msg_type | Msg_text |
+————+———+———-+———-+
| test.testf | analyze | status | OK |
+————+———+———-+———-+
1 row in set (0.21 sec)
分別作出如下執行計劃:
mysql explain select * from test.testf where name= gaopeng
+—-+————-+——-+————+——+—————+——+———+——-+——+———-+——-+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+——-+————+——+—————+——+———+——-+——+———-+——-+
| 1 | SIMPLE | testf | NULL | ref | name | name | 63 | const | 1 | 100.00 | NULL |
+—-+————-+——-+————+——+—————+——+———+——-+——+———-+——-+
1 row in set, 1 warning (0.00 sec)
mysql explain select * from test.testf where name= gaopeng1
+—-+————-+——-+————+——+—————+——+———+——+——+———-+————-+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+——-+————+——+—————+——+———+——+——+———-+————-+
| 1 | SIMPLE | testf | NULL | ALL | name | NULL | NULL | NULL | 10 | 90.00 | Using where |
+—-+————-+——-+————+——+—————+——+———+——+——+———-+————-+
1 row in set, 1 warning (0.00 sec)
可以看到執行計劃是正確的,name= gaopeng 的只有一行選擇了索引,name= gaopeng1 的有 9 行走了全表。
按理說如果只是記錄不同的那么這兩個語句的選擇均為 1 /2, 應該會造成執行計劃錯誤,而 MYSQL 5.6 5.7 中
都做了正確的選擇,那是為什么呢?
其實原因就在于 eq_range_index_dive_limit 這個參數,我們來看一下 trace
T@2: | | | | | | | | | | | opt: (null): gaopeng1 = name = | T@3: | | | | | | | | | | | opt: (null): gaopeng = name = g
T@2: | | | | | | | | | | | opt: ranges: ending struct | T@3: | | | | | | | | | | | opt: ranges: ending struct
T@2: | | | | | | | | | | | opt: index_dives_for_eq_ranges: 1 | T@3: | | | | | | | | | | | opt: index_dives_for_eq_ranges: 1
T@2: | | | | | | | | | | | opt: rowid_ordered: 1 | T@3: | | | | | | | | | | | opt: rowid_ordered: 1
T@2: | | | | | | | | | | | opt: using_mrr: 0 | T@3: | | | | | | | | | | | opt: using_mrr: 0
T@2: | | | | | | | | | | | opt: index_only: 0 | T@3: | | | | | | | | | | | opt: index_only: 0
T@2: | | | | | | | | | | | opt: rows: 9 | T@3: | | | | | | | | | | | opt: rows: 1
T@2: | | | | | | | | | | | opt: cost: 11.81 | T@3: | | | | | | | | | | | opt: cost: 2.21
我們可以看到 index_dives_for_eq_ranges 均為 1,rows: 9 rows: 1 都是正確的,那么可以確定是 index_dives_for_eq_ranges 的作用,實際上
這是一個參數 eq_range_index_dive_limit 來決定的(equality range optimization of many-valued comparisions),默認為
mysql show variables like %eq%
+————————————–+——-+
| Variable_name | Value |
+————————————–+——-+
| eq_range_index_dive_limit | 200 |
在官方文檔說這個取值是等值范圍比較的時候有多少個需要比較的值
如:
id=1 or id=2 or id=3 那么他取值就是 3 +1=4
而這種方法會得到精確的數據,但是增加的是時間成本,如果將
eq_range_index_dive_limit 設置為 1:則禁用此功能
eq_range_index_dive_limit 設置為 0:則始終開啟
eq_range_index_dive_limit 設置為 N:則滿足 N - 1 個這樣的域。
那么我們設置為 eq_range_index_dive_limit=1 后看看
mysql explain select * from test.testf where name= gaopeng1
+—-+————-+——-+————+——+—————+——+———+——-+——+———-+——-+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+——-+————+——+—————+——+———+——-+——+———-+——-+
| 1 | SIMPLE | testf | NULL | ref | name | name | 63 | const | 5 | 100.00 | NULL |
+—-+————-+——-+————+——+—————+——+———+——-+——+———-+——-+
1 row in set, 1 warning (0.00 sec)
mysql explain select * from test.testf where name= gaopeng
+—-+————-+——-+————+——+—————+——+———+——-+——+———-+——-+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+—-+————-+——-+————+——+—————+——+———+——-+——+———-+——-+
| 1 | SIMPLE | testf | NULL | ref | name | name | 63 | const | 5 | 100.00 | NULL |
+—-+————-+——-+————+——+—————+——+———+——-+——+———-+——-+
1 row in set, 1 warning (0.00 sec)
可以看到執行計劃已經錯誤 name= gaopeng1 明顯不應該使用索引,我們再來看看 trace
T@3: | | | | | | | | | | | opt: ranges: ending struct
T@3: | | | | | | | | | | | opt: index_dives_for_eq_ranges: 0
T@3: | | | | | | | | | | | opt: rowid_ordered: 1
T@3: | | | | | | | | | | | opt: using_mrr: 0
T@3: | | | | | | | | | | | opt: index_only: 0
T@3: | | | | | | | | | | | opt: rows: 5
T@3: | | | | | | | | | | | opt: cost: 7.01
index_dives_for_eq_ranges: 0 rows: 5 這個 5 就是 10*1/ 2 導致的, 而 index_dives_for_eq_ranges= 0 就是禁用了
到此,相信大家對“MYSQL5.6 5.7 處理數據分布不均的問題分析”有了更深的了解,不妨來實際操作一番吧!這里是丸趣 TV 網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!