• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase
您的位置:首页 > 数据库 >Mysql > MySQL Internals Optimizer

MySQL Internals Optimizer

作者:匿名 字体:[增加 减小] 来源:互联网 时间:2018-12-05

匿名通过本文主要向大家介绍了MySQL,Optimizer等相关知识,希望本文的分享对您有所帮助
优化器(The Optimizer)

这篇描述MySQL查询优化器的工作原理。MySQL查询优化器主要为执行的查询决断最有效的路线(routine,走向)。

一。源代码和概念


这部分讨论优化器关键概念,术语,及在MySQL源代码怎么对应的。

1.定义

狭义定义:优化器,就是DBMS为查询时决断要往哪种执行路径的一系列路线。

MySQL是经常调整查询的路线,所以你得把这篇描述的逻辑和在源代码里的做比较。为了使比较容易些,这里会包含相关文件和路径的注解,例如源代码/sql/sql_select.cc,optimize_cond()函数。

当一个查询被转成另一种查询时,其结果是一样的,就会发生语句转化。如下这个查询

SELECT ... WHERE 5 = a
就会被转化成为


SELECT ... WHERE a = 5
最明显的语句转化是少的,有些语句转化,是为了更快的执行。

2.优化器源代码

如下伪代码显示了/sql/sql_select.cc中handle_select()函数的逻辑结构。(源代码/sql/sql_select.cc处理SQL查询)

handle_select()
mysql_select()
JOIN::PRepare()
setup_fields()
JOIN::optimize() /* optimizer is from here ... */
optimize_cond()
opt_sum_query()
make_join_statistics()
get_quick_record_count()
choose_plan()
/* Find the best way to access tables */
/* as specified by the user. */
optimize_straight_join()
best_access_path()
/* Find a (sub-)optimal plan among all or subset */
/* of all possible query plans where the user */
/* controls the exhaustiveness of the search. */
greedy_search()
best_extension_by_limited_search()
best_access_path()
/* Perform an exhaustive search for an optimal plan */
find_best()
make_join_select() /* ... to here */
JOIN::exec()
缩进行显示了哪个函数调用哪个函数,如handle_select()函数调用mysql_select()函数,mysql_select()函数会调用JOIN::prepare()、JOIN::optimize()、JOIN::exec(),以及类推。mysql_select()函数的第一部分是调用JOIN::prepare(),此函数用来上下文分析、元数据建立和一些语句转化。查询优化器函数JOIN::optimize()和其所有优化处理中的子路线。当执行完JOIN::optimize()函数后,JOIN::exec()接管并完成JOIN::optimize()函数优化决断后的执行工作。

虽然有JOIN字出现,其实查询优化器的工作会处理所有的查询类型,不单单JOIN联接查询。

二。首要优化


这部分讨论服务器执行的最重要优化。


1.优化常数关系

常数等值传递


如下的表达式会发生语句转化:

WHERE column1 = column2 AND column2 = 'x'
这种表达式,众所周知,如果A=B && B=C => A=C(可等值传递),上句表达式转化后变成:


WHERE column1='x' AND column2='x'

当且仅当,操作符为如下的任何一个,在column1 <操作符> column2条件中就会发生语句转化:

=, <, >, <=, >=, <>, <=>, LIKE
注意:等值传递的转化,不适合于BETWEEN。可能也不适合于LIKE,这是后话。


常数等值传递同样发生在循环中,前一步传递的输出作为后一步传递的输入。


源代码见/sql/sql_select.cc,change_cond_ref_to_const()函数。或/sql/sql_select.cc,propagate_cond_constants()函数。

剔除死代码


总是TRUE的条件会发生语句转化,如:

WHERE 0=0 AND column1='y'
这种情况下,第一个条件会被剔除,最后为:


column1='y'
源代码见/sql/sql_select.cc,remove_eq_conds()。

总是FLASE的条件也会发生语句转化,如:

WHERE (0 = AND s1 = OR s1 = 7
小括号和前两个条件总是FLASE,最后为:


WHERE s1 = 7

还有一些情况下,当WHERE语句中代表不可能的条件,查询优化器可能会全部剔除语句,如下:

WHERE (0 = AND s1 = 5)
因为这条件永远不为TRUE,在EXPLAIN分析中会显示Impossible WHERE。简单地说,MySQL会说WHERE条件被优化过。


如果一个字段不能为NULL,优化器会剔除所有不相关的IS NULL的条件,这样

WHERE not_null_column IS NULL
这种条件总为FLASE情况;且


WHERE not_null_column IS NOT NULL
这种条件总为TRUE情况,所以这种字段查询的条件也被剔除。这种判断是很微妙的。举个例:在一个OUT JOIN外联接,被定义成NOT NULL字段仍然含有NULL值,优化器就会单独排除IS NULL条件在这种特殊情况中。

优化器不会检查所有的Impossible WHERE的条件,因为这方面可能性太多了。例如:


CREATE TABLE Table1 (column1 CHAR(1));
...
SELECT * FROM Table1 WHERE column1 = 'Popgo';
优化器不会剔除这种查询的条件,即使在CREATE TABLE定义中使之成为不可能的条件。


可合并的常数值


如下表达式会发生语句转化:

WHERE column1 = 1 + 2
最后为:


WHERE column1 = 3
在之前说的常数等值传递 ,优化器很容易将这种查询语句合并在一起。这操作就简化了结果。

常数值和常数表

MySQL常数值,有时不单单指在查询的SQL语句的字面意思上,也可在常数表(constant tables)的内容里。常数表(constant tables)被定义为:

1。无记录或一条记录的表


2。表的表达式被WHERE条件约束,而且包含的表达式形式column = "constant",或者表的主键的所有字段,或者任何唯一键的所有字段(唯一键的字段定义为NOT NULL)


例如,Table0表的定义包含:

... PRIMARY KEY (column1,column2)
然后,查询表达式:


FROM Table0 ... WHERE column1=5 AND column2=7 ...
会返回常数表(constant tables)。更多简单地,如果Table1表的定义包含:


... unique_not_null_column INT NOT NULL UNIQUE
然后,查询表达式:


FROM Table1 ... WHERE unique_not_null_column=5
也会返回常数表(constant tables)。


这个规则指一个常数表(constant tables)至多有一条记录值。MySQL就会优先评估是否为常数表(constant tables),并找出那个值。这样,MySQL会将这值插入查询语句。如这个例子:

SELECT Table1.unique_not_null_column, Table2.any_column
FROM Table1, Table2
WHERE Table1.unique_not_null_column = Table2.any_column
AND Table1.unique_not_null_column = 5;
MySQL评估这语句时,首先就会发现,按照常数表(constant tables)的第二点定义,查询条件为unique_not_null_column的表Table1是一个常数表(constant tables),它就会取得这个值。


如果取值失败,也就是在表Table1里unique_not_null_column = 没值,EXPLAIN后结果:


Impossible WHERE noticed after reading const tables
相反,如果取值成功,也就是在表Table1里unique_not_null_column = 为一条记录值,MySQL会转化为如下语句:


SELECT 5, Table2.any_column
FROM Table1, Table2
WHERE 5 = Table2.any_column
AND 5 = 5;

事实上,这是一个很好的例子。优化器因前面提到的常数等值传递进行一些语句转化。另外,为什么要先描述常数等值传递,因为它在MySQL确认什么是常数表(constant tables)前就先进行了。优化器步骤的顺序,有时是有差别。


虽然很多查询都没常数表(constant tables)参考。应该牢记,以后无论什么时候,常数constant字被提及,它是指任何一个字面上的值或者一个常数表(constant tables)的内容。

2.优化JOIN联接


这部分讨论优化JOIN联接的不同方法。注意:JOIN联接不单单指JOIN类型,而是所有条件查询的类型。有些人更喜欢叫access type。

确定JOIN联接类型


当评估查询条件表达式时,MySQL会确定它是属于哪个JOIN联接类型。

如下有记录在档的JOIN类型,从最好到最坏的排序下来:

system:常数表(constant tables)的system类型
const:常数表(constant tables)
eq_ref:相等关系的唯一或主键索引
ref:相等关系的索引,此索引的值不能为NULL
ref_or_null:相等关系的索引,此索引的值可能为NULL
range:有关联的索引,如BETWEEN,IN,>=,LIKE等
index:顺序扫描索引
ALL:顺序扫描整个表数据

源代码见/sql/sql_select.h,enum join_type{}。另外,还有一小部分没记录在档,为了子查询的JOIN联接类型。

优化器利用JOIN联接类型选择一个驱动表达式,如下:

SELECT *
FROM Table1
WHERE indexed_column = AND unindexed_column = 6
如果indexed_column有比较好的JOIN联接类型,它更可能成为驱动表达式。对它来说,你也会遇到各种不同的例外,但对这句描述,是第一个简单的优化法则。


对驱动来说,什么

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 分享下mysql各个主要版本之间的差异
  • MySQL essential版本和普通版本有什么区别?
  • redhat 5.4下安装MYSQL全过程
  • 如何用SQL命令查看Mysql数据库大小
  • 解析mysql中如何获得数据库的大小
  • 解析mysql修改为utf8后仍然有乱码的问题
  • 5个常用的MySQL数据库管理工具详细介绍
  • 解析在MySQL里创建外键时ERROR 1005的解决办法
  • 解析远程连接管理其他机器上的MYSQL数据库
  • mysql 精简过程(删除一些文件)

相关文章

  • 2018-12-05Sql 四大排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介
  • 2018-12-05MySQL高级四——自定义条件和处理
  • 2017-05-11MySQL 通过索引优化含ORDER BY的语句
  • 2018-12-05详解数据库MySQL中文乱码解决办法总结(图文)
  • 2017-05-11mysql unix准换时间格式查找指定日期数据代码
  • 2018-12-05MySQL 1303错误的解决方法(navicat)
  • 2017-05-11Mysql中的Datetime和Timestamp比较
  • 2018-12-05MySQL插入中文不乱码的5种方法_MySQL
  • 2017-05-11mysql 设置查询缓存
  • 2018-12-05如何快速掌握基本MySQL?

文章分类

  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase

最近更新的内容

    • 利用mysql的inet_aton()和inet_ntoa()函数存储IP地址的方法分享
    • 根据status信息对MySQL服务器进行优化
    • 如何创建SQL Server 2000故障转移群集
    • sphinxql如何得到结果数及show meta的详细说明
    • PL/SQL 日期时间类型函数及运算
    • plsql连接oracle数据库报ora 12154错误解决方法
    • mysql管理工具之MySQL-front的使用
    • mysql insert的几点操作(DELAYED,IGNORE,ON DUPLICATE KEY UPDATE )
    • 一个效率很高的汉字转拼音首字母的函数
    • 详细介绍mysql5.7创建用户授权删除用户撤销授权的示例代码

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有