mysqlin子查询原理_mysql子查询(in)的实现

更新时间:2023-06-19 07:26:06 阅读: 评论:0

mysqlin⼦查询原理_mysql⼦查询(in)的实现(转载)
In⼦查询的原理
1. in原理
此调研的背景是同样的lect结果为什么使⽤⼦查询会⽐不使⽤⼦查询慢。我们使⽤的数据库还是mysql官⽅的employees。进⾏的实验操作为下⾯两个语句:
⽅法⼀:explain lect sql_no_cache
employees e on (e.emp_p_no) straight_joinsalaries s on
(s.emp_p_no) der='F' and s.salary=90930;
图1直接使⽤join
⽅法⼆:explain lect sql_no_cache * from titles t p_no
in (p_no from salaries s, employees e where
图2使⽤in的⼦查询
在下⾯的讨论中我们直接使⽤直接join和in的称呼来代表两种不同的情况。(注:在我们的实验中第⼀种情况u
3.5s;第⼆种情况u 5.7s)
⾸先我们来解释⼀下图2的dependent
subquery是什么意思:⼿册上的解释是,⼦查询中的第⼀个lect,取决于外⾯的查询。就这么⼀句话,其实它表达的意思是(以我们图2的表来说明)⼦查询(e
join
t)的第⼀个表(e)的查询⽅式依赖于外部(t表)的查询。换句话说就是e表的检索⽅式依赖于t表的数据,如这⾥t表得到的记录
阳春白雪的意思
in)刚好可以被e表作为eq_ref⽅式来获得它的相应的记录;换种写法如果此时t表扫描第⼀条记录得到的t.emp_no为10001的话,那么后⾯⼦查询的语句就类似于这样的语句:
p_no from salaries s, employee where
奥运会2016通过这个解释我们可以知道:对于上⾯的两种⽅式,它们使⽤的索引及读取数据的过程及⽅法是⼀样的,全表扫描t表,将t的每条记录传递给e表,e表通过eq_ref索引⽅式来获得记录判断⾃⾝的条件,然后再传递给s给,s表使⽤ref⽅式来获得记录,再判断⾃⾝的条件是否也得到满⾜,如果也满⾜的话,则找到⼀个满⾜此查询的语句。那么为什么这两种情况会有性能上的差距了?
⾸先我们通过bt上看⼀下,两的具体执⾏流程,看它们的区别在哪⾥?
#0 evaluate_join_record (join=0x6fe0f10, join_tab=0x6fe2b28, error=0)
at sql_lect:11414
#1 0x00000000005e41e8 in sub_lect
(join=0x6fe0f10, join_tab=0x6fe2b28,
end_of_records=)
at sql_lect:11384 【s表】
#2 0x00000000005e3f5a in evaluate_join_record (join=0x6fe0f10, join_tab=0x6fe28d0, error=
out>) at sql_lect:11511
#3 0x00000000005e41e8 in sub_lect
注意力不集中是什么原因
(join=0x6fe0f10, join_tab=0x6fe28d0,
end_of_records=)
at
sql_lect:11384 【e表】
#4 0x00000000005e3f5a in evaluate_join_record (join=0x6fe0f10, join_tab=0x6fe2678, error=
out>) at sql_lect:11511
#5 0x00000000005e4215 in sub_lect
(join=0x6fe0f10, join_tab=0x6fe2678,
end_of_records=)
at
sql_lect:11391 【t表】
#6 0x0000000000601d30 in do_lect
(join=0x6fe0f10, fields=0x6f819a0, table=0x0, procedure=0x0) at sql_lect:11140
石榴有什么营养#7 0x000000000060a479 in JOIN::exec
(this=0x6fe0f10) at sql_lect:2314
#8 0x000000000060ae0f in mysql_lect
(thd=0x6f7f980, rref_pointer_array=0x6f81a68, tables=0x6fd5198, wild_num=0, fields=@0x6f819a0,
conds=0x6fdd218, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, lect_options=2147764736, result=0x6fdd398, unit=0x6f81470,
lect_lex=0x6f81898) at sql_lect:2509
#9 0x000000000060b481 in handle_lect
(thd=0x6f7f980, lex=0x6f813d0, result=0x6fdd398,
tup_tables_done_option=0) at sql_lect:269
#10 0x000000000054c71a in execute_sqlcom_lect (thd=0x6f7f980,
all_tables=0x6fd5198) at sql_par:5075
#11 0x000000000055538c in mysql_execute_command (thd=0x6f7f980) at
sql_par:2271
#12 0x000000000055ebd3 in mysql_par (thd=0x6f7f980,
表1 join⽅式的bt
通过该bt我们也可以清楚的看到三层nest-loop的过程;注:通过在每⼀层的sub_lect处查看join_tab->table->alias变量我们可以此时具体操作的表。
#0 evaluate_join_record (join=0x6fe11d8, join_tab=0x6fe5148, error=0)
at sql_lect:11414
#1 0x00000000005e41e8 in sub_lect
(join=0x6fe11d8, join_tab=0x6fe5148,
end_of_records=)
at
路由器登陆密码sql_lect:11384 【s表】
#2 0x00000000005e3f5a in evaluate_join_record (join=0x6fe11d8,
join_tab=0x6fe4ef0, error=
out>) at sql_lect:11511
#3 0x00000000005e41e8 in sub_lect
(join=0x6fe11d8, join_tab=0x6fe4ef0,
end_of_records=)
at
sql_lect:11384 【e表】
#4 0x0000000000601d30 in do_lect
(join=0x6fe11d8, fields=0x6fd5300, table=0x0, procedure=0x0) at
sql_lect:11140
#5 0x000000000060a479 in JOIN::exec
(this=0x6fe11d8) at sql_lect:2314
#6 0x00000000004d5102
in sublect_single_lect_engine::exec (this=0x6fdcda0)
at item_sublect:1987
#7 0x00000000004d26b1
in Item_sublect::exec (this=0x6fdccb0)
at item_sublect:280
#8 0x00000000004d1aaa in
Item_in_sublect::val_bool (this=0x6fe11d8) at
item_sublect:880
#9 0x0000000000438821 in Item::val_bool_result
(this=0x6fe11d8) at item.h:745
#10 0x0000000000476941 in Item_in_optimizer::val_int
(this=0x6fe2a58) at item_cmpfunc:1833
#11
0x00000000005e3d9a in evaluate_join_record (join=0x6fdce98,
join_tab=0x6fe3538, error=
out>) at sql_lect:11434
#12 0x00000000005e4215 in sub_lect (join=0x6fdce98,
join_tab=0x6fe3538, end_of_records=
out>) at
sql_lect:11391 【t表】
#13 0x0000000000601d30 in do_lect (join=0x6fdce98,
fields=0x6f819a0, table=0x0, procedure=0x0) at
sql_lect:11140
#14 0x000000000060a479 in JOIN::exec (this=0x6fdce98) at
sql_lect:2314
#15 0x000000000060ae0f in mysql_lect (thd=0x6f7f980,
rref_pointer_array=0x6f81a68, tables=0x6fd4d90, wild_num=1,
fields=@0x6f819a0,
conds=0x6fdccb0, og_num=0, order=0x0, group=0x0, having=0x0,
proc_param=0x0, lect_options=2147764736, result=0x6fdce78,凉粉的功效与作用
unit=0x6f81470,
lect_lex=0x6f81898) at sql_lect:2509
#16 0x000000000060b481 in handle_lect (thd=0x6f7f980,
lex=0x6f813d0, result=0x6fdce78, tup_tables_done_option=0) at
sql_lect:269
#17 0x000000000054c71a in execute_sqlcom_lect (thd=0x6f7f980,
all_tables=0x6fd4d90) at sql_par:5075
#18 0x000000000055538c in mysql_execute_command (thd=0x6f7f980) at sql_par:2271
#19 0x000000000055ebd3 in mysql_par (thd=0x6f7f980,
表2 in⽅式的bt
通过这两个表我们可以发现在表t与表[e,s]之前插⼊了⼀些其它的函数,并且这个插⼊的时机是在t表执⾏evaluate_join_record函数时调⽤lect_cond_result=
test(lect_cond->val_int());判断它所拥有的条件是否满⾜时进⼊的。对于表1直接join的情况该过程是没有被执⾏的因为它没有⾃⾝的where
cond。对于表2
in的⽅式,这个条件可能是由于在前⾯执⾏optimize时,确定外部查询的执⾏计划时确定的,这⾥我们不再去确认。正常的情况这个test如果有条件的话那么应该执⾏相应的条件判断如对于e表它最终调⽤的判断函数为int
成人性色Arg_comparator::compare_int_signed();⽽在这⾥对于有⼦查询的它调⽤的⽅法是:Item_sublect::exec,⽽它最终⼜调⽤各⾃的engine->exec(),如这⾥它调⽤的是这个sublect_single_lect_engine::exec⽅法,如果是第⼀次调⽤该函数的话那么就先执⾏⼀次join->optimize(),即对⼦查询(内部查询)进⾏优化,⽽在mysql_lect时调⽤的join->optimize()只是对外部查询进⾏优化,它并不包括内部查询的优化(执⾏计划等,另外对于直接join的话没有所谓的内外部查询那么它的整个执⾏计划就是mysql_lect完成),然后执⾏join-
>reinit(),最后再执⾏JOIN::exec;也就是说对于in这种情况t进⾏全表扫描,那么它总共有443310,那么这⼏个函数就要被调⽤443310多次(join->optimize()除外,它在第⼀次调⽤⼦查询确认执⾏计划之后就不再调⽤)。
我们可以通过下⾯的图来反应这两种过程:
图3 join⽅式的执⾏过程
图4 in⽅式的执⾏过程
上⾯就是in⼦查询的实现过程。下⾯我们将讨论为什么in⽅式与join⽅式性能差的原因?
2. In⽐join慢的原因
⾸先我们通过oprofile来测试⼀下,两种情况各⾃的性能损耗在哪⾥?
Join
In
samples % symbol
name
444 11.2065 buf_calc_page_new_checksum
337 8.5058 rec_get_offts_func
326 8.2282 pthread_mutex_unlock
245 6.1837 pthread_mutex_lock
240 6.0575 cmp_dtuple_rec_with_match
226 5.7042 row_arch_for_mysql
218 5.5023 row_l_store_mysql_rec
104 2.6249 code_state
103 2.5997 ha_inrt_for_fold
97 2.4483 page_cur_arch_with_match
83 2.0949 pthread_mutex_trylock

本文发布于:2023-06-19 07:26:06,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/989318.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:查询   优化   条件   记录   情况   判断   性能   过程
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图