mysql 优化器关联查询_MySQL 查询优化器(二)
1.6多个查询字段(常量条件)
多个查询字段的查询处理逻辑如下所示:
JOIN:prepare阶段
setup_tables():同1.1测试。
setup_fields():同1.1测试。
setup_conds():同1.4测试。
JOIN:optimize阶段
optimize_cond():类似1.4测试,不同之处在于查询的where条件中有恒等常量,在优化过程中会调用remove_eq_conds将1=1条件删除。
make_join_statistics():与1.4测试类似,由于where条件查询有两个,并且其中一个条件可以通过索引查询。因此首先通过调用update_ref_and_keys()(sql\sql_select.cc:3967)函数,查找可以使用索引的字段。
SQL_SELECT::test_quick_select():同1.5索引测试
get_key_scans_params():同1.5索引测试。
choose_plan():同1.3测试。
greedy_search():同1.3测试。
best_extension_by_limited_search():同1.5索引测试。
JOIN:exec阶段
以下操作同1.3测试。
通过测试可以看出,对于常量等式对查询优化器来说没有任何意义,会在optimize_conds时将常量等式删除。建议在查询的where条件中不要出现对查询没有意义的条件,尽管查询优化器会将没有意义的查询条件去除,并等式的右值条件尽可能的转化为常量,例如将类似(a=b, b=1)类型转化为(a=1, b=1)。但从优化角度来看,尽可能在sql语句中就避免这些优化逻辑。查询计划的类型为ref,利用索引查找。
查询student中多个普通字段(包含常量条件),执行SQL:
SELECT std_id, std_name, std_spec, std_***, std_age FROM student WHERE std_name="fff" AND std_age > 20 AND 1=1;
对应的查询计划如下所示:
查询计划跟单个查询条件的索引查询的执行相同,这说明增加非索引字段的查询,主要用于从索引查询的结果中过滤记录。如果添加的索引不能过滤掉大多数的查询记录的话,普通查询条件过滤记录的代价也会较大。因此,建立索引的目的应该是尽可能的过滤掉查询记录,那么增加索引才有效,否则索引查询反而会增加查询的代价。
1.7 LIMIT条件
Limit条件查询的逻辑处理流程如1.5普通条件查询类似,唯一不同点在于JOIN::exec()处理过程中,取结果集时,根据limit限制的值来进行过滤。因此,当查询结果集较多的情况下,limit条件可以减少结果集传递的代价。
查询student中limit条件,执行SQL:
SELECT std_id, std_name, std_spec, std_***, std_age FROM student WHERE std_spec = "computer" LIMIT 5;
1.8 IN条件
In条件查询的逻辑处理流程如下所示:
JOIN:prepare阶段
setup_tables():同1.1测试。
setup_fields():同1.1测试。
setup_conds():同1.4测试。
JOIN:optimize阶段
optimize_cond():同1.4测试。
make_join_statistics():与1.5索引测试类似,不同之处在于调用update_ref_and_keys()(sql\sql_select.cc:3967)函数时,查找查询字段是否可以用索引字段时,没有找到可以使用的索引。但是由于查询字段上有索引,因此调用get_quick_record_count()函数的实现逻辑SQL_SELECT::test_quick_select()函数构建查询树时,转化为OR的方式处理,并将查找的键值进行合并,形成查询范围。
SQL_SELECT::test_quick_select():同1.5索引测试
get_key_scans_params():同1.5索引测试。
choose_plan():同1.3测试。
greedy_search():同1.3测试。
best_extension_by_limited_search():同1.5测试。尽管查询字段有索引,但是调用update_ref_and_keys()对查询字段进行检查是否可以使用索引时,没有可以使用的索引。因此,不同于1.5的索引测试的过程,而是与普通查询测试相同。
JOIN:exec阶段
以下操作类似1.3测试。不同之处在于查询的范围通过搜索查询树,减小了查询的范围。
查询student中in条件(索引),执行SQL:
SELECT std_id, std_name, std_spec, std_***, std_age FROM student WHERE std_name in ("bbb","ccc","ddd");
对应的查询计划如下所示:
从逻辑处理过程和查询计划可以看出,IN条件的处理是转化为OR的条件来处理,这一点从查询树的构建可以看出。查询计划类型为range,没有使用索引直接查询,而是通过索引查找来构建查询树,减小查询的范围。
IN条件的查询字段为普通字段时,由于查询字段无索引,因此,不会通过调用get_quick_record_count()函数的实现逻辑SQL_SELECT::test_quick_select()函数构建查询树,从而形成查询范围。而是直接执行JOIN::exec中进行全表扫描,通过查询条件过滤查询结果。
查询student中in条件(普通字段),执行SQL:
SELECT std_id, std_name, std_spec, std_***, std_age FROM student WHERE std_spec in ("math","information");
对应的查询计划如下所示:
通过查询计划可以看出,对没有索引的字段使用IN操作跟普通的1.5的普通字段查询测试相同。
通过对IN条件的整体测试发现,当查询的字段存在索引的情况下,查询优化器会利用查询字段的索引,构建查询树,减小查询的范围,然后通过查询优化数进行全扫描并返回查询结果。而在查询字段没有索引的情况下,查询计划和查询逻辑跟普通查询条件进行全表扫描一样,在执行全表扫描时,通过查询条件过滤查询结果。
1.9 GROUP BY条件、ORDER BY条件、HAVING条件联合
之所以将三个条件联合查询,而非单独测试,是由于这些条件一般都是组合使用才有效果。并且,单独测试不会凸显查询条件的全部处理逻辑,不利于更好的理解。
具体的查询处理逻辑如下所示:
JOIN:prepare阶段
setup_tables():同1.1测试。
setup_fields():同1.1测试。
setup_conds():同1.4测试。
setup_order():初始化order by列表。根据order by的字段,改变查询列表中查询字段的order by顺序。并调用find_order_in_list()函数,检查order by 的字段是否在select的字段中(调用find_item_in_list(),(sql\sql_base.cc:6835)),并查找order by列表中的字段是否在数据表中 (调用find_item_in_tables(),(sql\sql_base.cc:6602))。(sql\sql_select.cc:15037)(sql\sql_select.cc:14996)
setup_group():初始化group by列表,处理逻辑跟setup_order()的处理逻辑相同。调用find_order_in_list()函数,检查group by 的字段是否在select的字段中(调用find_item_in_list(),(sql\sql_base.cc:6835)),并查找group by列表中的字段是否在数据表中 (调用find_item_in_tables(),(sql\sql_base.cc:6602))。(sql\sql_select.cc:15037)(sql\sql_select.cc:14996)
having处理:having的初始化过程没有以具体的函数形式给出,但是处理逻辑类似group by。主要检查having条件的字段是否在查询列表中。由于having条件是查询字段的别名,因此在比较了查询列表后,发现该字段即结束。
JOIN:optimize阶段
optimize_cond():类似1.4测试,但不同之处在于进行优化的是having条件。
make_join_statistics():与1.3转化为group by后的测试类似。
choose_plan():同1.3测试。
greedy_search():同1.3测试。
best_extension_by_limited_search():同1.3测试。
calc_group_buffer():同1.3测试。
create_tmp_table():同1.3测试。
JOIN:exec阶段
以下操作同1.3测试类似,区别在于对临时表操作时,临时结果的过滤方式不同。生成临时结果的过程中,会调用聚合函数进行处理。
从处理逻辑来看,在JOIN::prepare阶段增加了初始化group、order、having条件。由于查询字段没有索引,因此需要进行全表扫描。与普通查询不同的执行过程在于在临时表操作时,临时结果的过滤处理不同。
查询student中group by、order by、having联合条件,执行SQL:
SELECT std_spec, COUNT(std_spec) cnt FROM student GROUP BY std_spec HAVING cnt > 3 ORDER BY cnt;
对应的查询计划如下所示:
从查询计划来看,与1.3测试完全一致。查询计划类型为ALL,进行全表扫描。
1.10 UNION条件
Union条件的查询处理逻辑如下所示:
mysql_union():Union条件处理逻辑。调用st_select_lex_unit::prepare()函数(sql\sql_union.cc:1172)对Union中的每条语句进行处理。
st_select_lex_unit::prepare():逐条执行JOIN:prepare()处理逻辑,为查询处理做准备工作,并调用select_union::create_result_table()(sql\sql_union.cc:117)函数创建临时表。
JOIN:prepare阶段:主要处理过程同1.4测试。
st_select_lex_unit::exec():逐条执行JOIN:optimize()处理逻辑,对每条查询语句进行优化。逐条执行JOIN:exec()处理逻辑,执行查询操作。
JOIN:optimize阶段:对于Union中的不同查询字段类型的语句,处理逻辑有所不同。Union的第一句的处理逻辑同1.4主键查询测试。Union的第二句的处理逻辑同1.5测试的索引字段处理。Union的第三句的处理逻辑同1.5测试的普通字段处理。
JOIN:exec阶段:对不同的Union中不同查询字段类型的语句,处理逻辑不同,并将查询的结果存储到临时表中。同JOIN:optimize阶段的对应关系相同。
st_select_lex_unit::init_prepare_fake_select_lex():构建一条查询语句,获取查询结果。
mysql_select():同1.1测试,获取查询结果。
从处理逻辑来看,UNION条件的处理相当于分别对不同的查询子句根据对应的查询条件类型进行处理。处理结束后,对分别的查询结果再次进行查询过滤。
查询student中union条件,执行SQL:
SELECT std_id, std_name, std_spec, std_***, std_age FROM student WHERE std_id=2012072306 UNION SELECT std_id, std_name, std_spec, std_***, std_age FROM student WHERE std_name="bbb" UNION SELECT std_id, std_name, std_spec, std_***, std_age FROM student WHERE std_spec="math";
对应的查询计划如下所示:
从查询计划来看,查询类型根据UNION中各个子句的查询字段类型,生成各自的查询计划。最后对查询结果,进行进一步的过滤查询。
mysql 优化器关联查询_MySQL 查询优化器(二)相关推荐
- mysql 关联查询_Mysql查询优化器,再也不会因为该什么时候建立索引发愁了
优化器的作用: 我们知道,一条SQL语句,可以有很多执行方式,最后都返回相同的结果,而优化器的作用就是找到最好的执行计划. 一.RBO-基于规则的优化器(rule) 系统内置的一套硬编码规则,根据规则 ...
- mysql数据库做关联查询_mysql 数据库join关联查询using(xxx)的作用
user表: id | name --------- 1 | libk 2 | zyfon 3 | daodao user_action表: user_id | action ------------ ...
- mysql外键关联查询_MySQL外键约束和多表联查
一.创建外键 #测试数据表 # 教师表,主表 CREATE TABLE teacher( id INT PRIMARY KEY AUTO_INCREMENT, name varchar(20), ag ...
- mysql一对多关联查询分页_mysql一对多关联查询分页错误问题的解决方法
xml问价中查询数据中包含list,需要使用collection .... .... 这样的查询系统封装的通用分页查询是不对的,所以需要自己sql中加入分页解决 SELECT you.nick_nam ...
- MySQL多表关联查询效率高点还是多次单表查询效率高,为什么?
这里写目录标题 MySQL多表关联查询对比多次单表查询,哪个效率高? 疑问: 高手解答: <阿里巴巴JAVA开发手册>里面写超过三张表禁止join 这是为什么?这样的话那sql要怎么写? ...
- mysql慢查询检查流程_简单谈谈MySQL优化利器-慢查询
慢查询 首先,无论进行何种优化,开启慢查询都算是前置条件.慢查询机制,将记录过慢的查询语句(事件),从而为DB维护人员提供优化目标. 检查慢查询是否开启 通过show variables like ' ...
- 关联查询mysql_《MySQL数据库》关联查询
原标题:<MySQL数据库>关联查询 一.关联查询 1.概念 在查询数据时,所需要的数据不只在一张表中,可能在两张或多张表中.这个时候,需要同时操作这些表来查询数据,即关联查询. 关联查询 ...
- SQL优化--使用关联查询代替子查询
SQL优化--使用关联查询代替子查询 测试例子: 子查询: select a.*, (select workflowname from workflowbase where id=workflowid ...
- mysql数据关联查询_《MySQL数据库》关联查询
原标题:<MySQL数据库>关联查询 一.关联查询 1.概念 在查询数据时,所需要的数据不只在一张表中,可能在两张或多张表中.这个时候,需要同时操作这些表来查询数据,即关联查询. 关联查询 ...
最新文章
- 计算机主机内置的地址码被称为,2016年职称计算机考试WPS_Office单选练习试题1
- Python数据结构学习笔记——链表:无序链表和有序链表
- js将百度坐标转为wgs84
- vc6可编译的 linux 源码,winpcap+vc6编译环境配置,以及获取网络设备列表的源代码...
- Java 算法 S01串
- java 分布式事务处理
- C#连接Oracle中文乱码问题解决方法
- 用c语言编写函数流程,C语言课程设计————写下流程图! 谢谢
- 一、Spring Boot整合redies
- 在CentOS 7 1804 中 安装 使用 GitLab 11.4.3-ee (企业版、社区版最新版、或任意版本)
- Linux常用软件包安装工具及配置方法(apt-get, pip, dpkg)
- 什么是数据库存储过程?
- openalyers 好玩的效果之蒙版图层
- python 3 12306余票查询脚本
- 【zz】陈硕:当析构函数遇到多线程──C++ 中线程安全的对象回调
- Spark on Hive Hive on Spark傻傻分不清?
- OKR教练:OKRs-E如何帮你落地OKR
- 不同excel根据某列相同字段值进行关联
- html 图片滑动验证码,selenium滑动验证码
- 威眼局域网监控软件3.7.2发布
热门文章
- Qt文档阅读笔记-Object Trees Ownership解析与实例(为何某些程序在被关闭的时候会崩溃)
- Qt工作笔记-对connect的第五个参数的研究
- WEB安全基础-点击劫持漏洞基础
- 服务器系统架构的评估,系统架构师:性能评估
- oracle脚本导入mysql数据库_oracle脚本导入mysql数据库
- 启动mysql 1067_启动mysql遇到1067问题
- python编辑程序模型_python并发编程之IO模型
- 性能测试的几个参数概念
- 【C语言笔记初级篇】第七章:结构体相关
- (计算机组成原理)第三章存储系统-第四节:主存储器和CPU的连接