MySQL:2020 端午节随笔(索引下探和唯一索引特殊执行计划)

一、索引数据下探

http://blog.itpub.net/7728585/viewspace-2660796/

/*
Get the number of rows in the range. This is done by calling
records_in_range() unless:

    1) The range is an equality range and the index is unique.
       There cannot be more than one matching row, so 1 is
       assumed. Note that it is possible that the correct number
       is actually 0, so the row estimate may be too high in this
       case. Also note: ranges of the form "x IS NULL" may have more
       than 1 mathing row so records_in_range() is called for these.
    2) a) The range is an equality range but the index is either 
          not unique or all of the keyparts are not used. 
       b) The user has requested that index statistics should be used
          for equality ranges to avoid the incurred overhead of 
          index dives in records_in_range().
       c) Index statistics is available.
       Ranges of the form "x IS NULL" will not use index statistics 
       because the number of rows with this value are likely to be 
       very different than the values in the index statistics.
*/

handler::multi_range_read_info_const

  • 等值条件,根据参数 eq_range_index_dive_limit 来判断是否进行下探 0 始终 1 始终不 >1 判断 or 的个数
  • 范围 始终下探

疑问:下探的采样范围和原理

下探栈

(gdb) bt
#0  handler::multi_range_read_info_const (this=0x7fff0576eb00, keyno=2, seq=0x7fffe8d3ddb0, seq_init_param=0x7fffe8d3ddf0, n_ranges_arg=0, bufsz=0x7fffe8d3dd00, flags=0x7fffe8d3dd04, cost=0x7fffe8d3e1e0)
    at /cdh/mysqldebug/percona-server-5.7.29-32/sql/handler.cc:6651
#1  0x0000000000ec4364 in DsMrr_impl::dsmrr_info_const (this=0x7fff0576ef70, keyno=2, seq=0x7fffe8d3ddb0, seq_init_param=0x7fffe8d3ddf0, n_ranges=0, bufsz=0x7fffe8d3e2e0, flags=0x7fffe8d3e2e4, 
    cost=0x7fffe8d3e1e0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/handler.cc:7391
#2  0x000000000198cbc1 in ha_innobase::multi_range_read_info_const (this=0x7fff0576eb00, keyno=2, seq=0x7fffe8d3ddb0, seq_init_param=0x7fffe8d3ddf0, n_ranges=0, bufsz=0x7fffe8d3e2e0, flags=0x7fffe8d3e2e4, 
    cost=0x7fffe8d3e1e0) at /cdh/mysqldebug/percona-server-5.7.29-32/storage/innobase/handler/ha_innodb.cc:23185
#3  0x0000000001733252 in check_quick_select (param=0x7fffe8d3e550, idx=0, index_only=false, tree=0x7fff040c0ed0, update_tbl_stats=true, mrr_flags=0x7fffe8d3e2e4, bufsize=0x7fffe8d3e2e0, cost=0x7fffe8d3e1e0)
    at /cdh/mysqldebug/percona-server-5.7.29-32/sql/opt_range.cc:10099
#4  0x000000000172a110 in get_key_scans_params (param=0x7fffe8d3e550, tree=0x7fff040c0e08, index_read_must_be_used=false, update_tbl_stats=true, cost_est=0x7fffe8d3e430)
    at /cdh/mysqldebug/percona-server-5.7.29-32/sql/opt_range.cc:5854
#5  0x0000000001723c21 in test_quick_select (thd=0x7fff04000bf0, keys_to_use=..., prev_tables=0, limit=18446744073709551615, force_quick_range=false, interesting_order=st_order::ORDER_NOT_RELEVANT, 
    tab=0x7fff057734a8, cond=0x7fff04007538, needed_reg=0x7fff057734e8, quick=0x7fffe8d40a38, ignore_table_scan=false) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/opt_range.cc:3108
#6  0x00000000014b2aa9 in get_quick_record_count (thd=0x7fff04000bf0, tab=0x7fff057734a8, limit=18446744073709551615) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_optimizer.cc:6013
#7  0x00000000014b2172 in JOIN::estimate_rowcount (this=0x7fff057730d0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_optimizer.cc:5760
#8  0x00000000014b05eb in JOIN::make_join_plan (this=0x7fff057730d0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_optimizer.cc:5117
#9  0x00000000014a4d06 in JOIN::optimize (this=0x7fff057730d0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_optimizer.cc:394
#10 0x000000000151f92b in st_select_lex::optimize (this=0x7fff04005d50, thd=0x7fff04000bf0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_select.cc:1018
#11 0x000000000151e053 in handle_query (thd=0x7fff04000bf0, lex=0x7fff040032a0, result=0x7fff04007780, added_options=0, removed_options=0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_select.cc:172
#12 0x00000000014d1d93 in execute_sqlcom_select (thd=0x7fff04000bf0, all_tables=0x7fff04006e58) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_parse.cc:5475
#13 0x00000000014cb119 in mysql_execute_command (thd=0x7fff04000bf0, first_level=true) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_parse.cc:3016
#14 0x00000000014d2e1b in mysql_parse (thd=0x7fff04000bf0, parser_state=0x7fffe8d424a0, update_userstat=false) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_parse.cc:5927
#15 0x00000000014c7a55 in dispatch_command (thd=0x7fff04000bf0, com_data=0x7fffe8d42c90, command=COM_QUERY) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_parse.cc:1539
#16 0x00000000014c688a in do_command (thd=0x7fff04000bf0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_parse.cc:1060
#17 0x00000000015fab28 in handle_connection (arg=0x3443230) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/conn_handler/connection_handler_per_thread.cc:325
#18 0x00000000018cad34 in pfs_spawn_thread (arg=0x3dd00c0) at /cdh/mysqldebug/percona-server-5.7.29-32/storage/perfschema/pfs.cc:2198
#19 0x00007ffff7bc6e65 in start_thread () from /lib64/libpthread.so.0
#20 0x00007ffff5fa088d in clone () from /lib64/libc.so.6


#0  btr_cur_search_to_nth_level (index=0x7fff0494e320, level=0, tuple=0x7fff04a619b0, mode=PAGE_CUR_GE, latch_mode=1025, cursor=0x7fffe8d39310, has_search_latch=0, 
    file=0x2311530 "/cdh/mysqldebug/percona-server-5.7.29-32/storage/innobase/btr/btr0cur.cc", line=5913, mtr=0x7fffe8d393b0) at /cdh/mysqldebug/percona-server-5.7.29-32/storage/innobase/btr/btr0cur.cc:798
#1  0x0000000001c047e9 in btr_estimate_n_rows_in_range_low (index=0x7fff0494e320, tuple1=0x7fff04a619b0, mode1=PAGE_CUR_GE, tuple2=0x7fff04a61a40, mode2=PAGE_CUR_G, nth_attempt=1)
    at /cdh/mysqldebug/percona-server-5.7.29-32/storage/innobase/btr/btr0cur.cc:5913
#2  0x0000000001c05239 in btr_estimate_n_rows_in_range (index=0x7fff0494e320, tuple1=0x7fff04a619b0, mode1=PAGE_CUR_GE, tuple2=0x7fff04a61a40, mode2=PAGE_CUR_G)
    at /cdh/mysqldebug/percona-server-5.7.29-32/storage/innobase/btr/btr0cur.cc:6248
#3  0x0000000001981cd7 in ha_innobase::records_in_range (this=0x7fff04954b00, keynr=1, min_key=0x7fffe8d3dc00, max_key=0x7fffe8d3dc20)
    at /cdh/mysqldebug/percona-server-5.7.29-32/storage/innobase/handler/ha_innodb.cc:15147
#4  0x0000000000ec2adb in handler::multi_range_read_info_const (this=0x7fff04954b00, keyno=1, seq=0x7fffe8d3ddb0, seq_init_param=0x7fffe8d3ddf0, n_ranges_arg=0, bufsz=0x7fffe8d3dd00, flags=0x7fffe8d3dd04, 
    cost=0x7fffe8d3e1e0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/handler.cc:6716
#5  0x0000000000ec4364 in DsMrr_impl::dsmrr_info_const (this=0x7fff04954f70, keyno=1, seq=0x7fffe8d3ddb0, seq_init_param=0x7fffe8d3ddf0, n_ranges=0, bufsz=0x7fffe8d3e2e0, flags=0x7fffe8d3e2e4, 
    cost=0x7fffe8d3e1e0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/handler.cc:7391
#6  0x000000000198cbc1 in ha_innobase::multi_range_read_info_const (this=0x7fff04954b00, keyno=1, seq=0x7fffe8d3ddb0, seq_init_param=0x7fffe8d3ddf0, n_ranges=0, bufsz=0x7fffe8d3e2e0, flags=0x7fffe8d3e2e4, 
    cost=0x7fffe8d3e1e0) at /cdh/mysqldebug/percona-server-5.7.29-32/storage/innobase/handler/ha_innodb.cc:23185
#7  0x0000000001733252 in check_quick_select (param=0x7fffe8d3e550, idx=0, index_only=false, tree=0x7fff04a26af0, update_tbl_stats=true, mrr_flags=0x7fffe8d3e2e4, bufsize=0x7fffe8d3e2e0, cost=0x7fffe8d3e1e0)
    at /cdh/mysqldebug/percona-server-5.7.29-32/sql/opt_range.cc:10099

二、唯一索引的特别执行计划

root@localhost:test:06:04:57>select *from t_un;
+----+------+---------+
| id | id2 | name |
+----+------+---------+
| 1 | 1 | NULL |
| 2 | 2 | NULL |
| 3 | 3 | NULL |
| 4 | 4 | NULL |
| 5 | 5 | gaopeng |
+----+------+---------+
5 rows in set (2.74 sec)

但是实际都是做的唯一索引,不会导致全表扫描。

测试:
id2是唯一索引

root@localhost:test:06:04:57>select *from t_un;
+----+------+---------+
| id | id2 | name |
+----+------+---------+
| 1 | 1 | NULL |
| 2 | 2 | NULL |
| 3 | 3 | NULL |
| 4 | 4 | NULL |
| 5 | 5 | gaopeng |
+----+------+---------+
5 rows in set (2.74 sec)

  • 唯一索引没有适合的值
    root@localhost:test:05:56:54>desc select *from t_un where id2=10 ;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
    | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | no matching row in const table |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
    1 row in set, 1 warning (1.75 sec)
  • 唯一索引有适合的值,但是where条件过滤掉了
    root@localhost:test:05:57:03>desc select *from t_un where id2=1 and name='test' ;
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------------------------------------------+
    | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------------------------------------------+
    | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE noticed after reading const tables |
    +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------------------------------------------+
    1 row in set, 1 warning (2.18 sec)

ERROR:
No query specified

我看了交互信息,只看到一条数据,所以这种情况实际上也是用的唯一索引没有问题。

实际访问数据栈

#0  row_search_mvcc (buf=0x7fff0576e210 "\376\001", mode=PAGE_CUR_GE, prebuilt=0x7fff0414dc80, match_mode=1, direction=0) at /cdh/mysqldebug/percona-server-5.7.29-32/storage/innobase/row/row0sel.cc:4755
#1  0x0000000001978a27 in ha_innobase::index_read (this=0x7fff0576eb00, buf=0x7fff0576e210 "\376\001", key_ptr=0x7fff057746e0 "", key_len=5, find_flag=HA_READ_KEY_EXACT)
    at /cdh/mysqldebug/percona-server-5.7.29-32/storage/innobase/handler/ha_innodb.cc:9970
#2  0x0000000000ec9c08 in handler::index_read_map (this=0x7fff0576eb00, buf=0x7fff0576e210 "\376\001", key=0x7fff057746e0 "", keypart_map=1, find_flag=HA_READ_KEY_EXACT)
    at /cdh/mysqldebug/percona-server-5.7.29-32/sql/handler.h:2990
#3  0x0000000000ec576f in handler::index_read_idx_map (this=0x7fff0576eb00, buf=0x7fff0576e210 "\376\001", index=1, key=0x7fff057746e0 "", keypart_map=1, find_flag=HA_READ_KEY_EXACT)
    at /cdh/mysqldebug/percona-server-5.7.29-32/sql/handler.cc:8051
#4  0x0000000000ebb3b2 in handler::ha_index_read_idx_map (this=0x7fff0576eb00, buf=0x7fff0576e210 "\376\001", index=1, key=0x7fff057746e0 "", keypart_map=1, find_flag=HA_READ_KEY_EXACT)
    at /cdh/mysqldebug/percona-server-5.7.29-32/sql/handler.cc:3336
#5  0x00000000014862a9 in read_const (table=0x7fff0546eb00, ref=0x7fff05773b50) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_executor.cc:2020
#6  0x0000000001485d8c in join_read_const_table (tab=0x7fff05773a80, pos=0x7fff05773c18) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_executor.cc:1905
#7  0x00000000014b1aeb in JOIN::extract_func_dependent_tables (this=0x7fff05773498) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_optimizer.cc:5645
#8  0x00000000014b058d in JOIN::make_join_plan (this=0x7fff05773498) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_optimizer.cc:5109
#9  0x00000000014a4d06 in JOIN::optimize (this=0x7fff05773498) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_optimizer.cc:394
#10 0x000000000151f92b in st_select_lex::optimize (this=0x7fff04005d50, thd=0x7fff04000bf0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_select.cc:1018
#11 0x000000000151e053 in handle_query (thd=0x7fff04000bf0, lex=0x7fff040032a0, result=0x7fff04007ba8, added_options=0, removed_options=0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_select.cc:172
#12 0x00000000014d1e8d in execute_sqlcom_select (thd=0x7fff04000bf0, all_tables=0x7fff04006fd0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_parse.cc:5490
#13 0x00000000014cb119 in mysql_execute_command (thd=0x7fff04000bf0, first_level=true) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_parse.cc:3016
#14 0x00000000014d2e1b in mysql_parse (thd=0x7fff04000bf0, parser_state=0x7fffe8d424a0, update_userstat=false) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_parse.cc:5927
#15 0x00000000014c7a55 in dispatch_command (thd=0x7fff04000bf0, com_data=0x7fffe8d42c90, command=COM_QUERY) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_parse.cc:1539
#16 0x00000000014c688a in do_command (thd=0x7fff04000bf0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/sql_parse.cc:1060
#17 0x00000000015fab28 in handle_connection (arg=0x3443230) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/conn_handler/connection_handler_per_thread.cc:325
#18 0x00000000018cad34 in pfs_spawn_thread (arg=0x3dd00c0) at /cdh/mysqldebug/percona-server-5.7.29-32/storage/perfschema/pfs.cc:2198
#19 0x00007ffff7bc6e65 in start_thread () from /lib64/libpthread.so.0
#20 0x00007ffff5fa088d in clone () from /lib64/libc.so.6
(gdb) c
Continuing.

Breakpoint 7, handler::multi_range_read_info_const (this=0x7fff0576eb00, keyno=2, seq=0x7fffe8d3ddb0, seq_init_param=0x7fffe8d3ddf0, n_ranges_arg=0, bufsz=0x7fffe8d3dd00, flags=0x7fffe8d3dd04, 
    cost=0x7fffe8d3e1e0) at /cdh/mysqldebug/percona-server-5.7.29-32/sql/handler.cc:6651
6651      ha_rows rows, total_rows= 0;

深入理解MySQL主从原理:https://www.jianshu.com/nb/43148932
个人微信:gaopp_22389860

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343