自制小工具大大加速MySQL SQL语句优化(附源码)

本文介绍了如何利用自制的小工具快速优化MySQL SQL语句,包括执行计划、统计信息、系统参数、优化器开关等多个方面。通过EXPLAIN命令深入理解SQL执行过程,使用SHOW TABLE STATUS和SHOW INDEX获取表和索引统计信息,调整系统参数如sort_buffer_size和join_buffer_size以提升性能。此外,还讨论了SQL性能分析器Query Profiler的使用,以及自研工具的调用方法、输出内容,帮助DBA高效完成优化工作。
摘要由CSDN通过智能技术生成

引言


优化SQL,是DBA常见的工作之一。如何高效、快速地优化一条语句,是每个DBA经常要面对的一个问题。在日常的优化工作中,我发现有很多操作是在优化过程中必不可少的步骤。然而这些步骤重复性的执行,又会耗费DBA很多精力。于是萌发了自己编写小工具,提高优化效率的想法。

那选择何种语言来开发工具呢?

对于一名DBA来说,掌握一门语言配合自己的工作是非常必要的。相对于shell的简单、perl的飘逸,Python是一种严谨的高级语言。其具备上手快、语法简单、扩展丰富、跨平台等多种优点。很多人把它称为一种“胶水”语言,通过大量丰富的类库、模块,可以快速搭建出自己需要的工具。

于是乎,这个小工具就成了我学习Python的第一个作业,我把它称之为“MySQL语句优化辅助工具”。而且从此以后,我深深爱上了Python,并开发了很多数据库相关的小工具,以后有机会介绍给大家。

(想自学习编程的小伙伴请搜索圈T社区,更多行业相关资讯更有行业相关免费视频教程。完全免费哦!)

一、优化手段、步骤

下面在介绍工具使用之前,首先说明下MySQL中语句优化常用的手段、方法及需要注意的问题。这也是大家在日常手工优化中,需要了解掌握的。

1、执行计划 — EXPLAIN命令

执行计划是语句优化的主要切入点,通过执行计划的判读了解语句的执行过程。在执行计划生成方面,MySQL与Oracle明显不同,它不会缓存执行计划,每次都执行“硬解析”。查看执行计划的方法,就是使用EXPLAIN命令。

1)基本用法
EXPLAIN QUERY

当在一个Select语句前使用关键字EXPLAIN时,MySQL会解释了即将如何运行该Select语句,它显示了表如何连接、连接的顺序等信息。

EXPLAIN EXTENDED QUERY

当使用EXTENDED关键字时,EXPLAIN产生附加信息,可以用SHOW WARNINGS浏览。该信息显示优化器限定SELECT语句中的表和列名,重写并且执行优化规则后SELECT语句是什么样子,并且还可能包括优化过程的其它注解。在MySQL5.0及更新的版本里都可以使用,在MySQL5.1里它有额外增加了一个过滤列(filtered)。

EXPLAIN PARTITIONS QUERY

显示的是查询要访问的数据分片——如果有分片的话。它只能在MySQL5.1及更新的版本里使用。

EXPLAIN FORMAT=JSON (5.6新特性)

另一个格式显示执行计划。可以看到诸如表间关联方式等信息。

2)输出字段

下面说明一下EXPLAIN输出的字段含义,并由此学习如何判断一个执行计划。

id

MySQL选定的执行计划中查询的序列号。如果语句里没有子查询等情况,那么整个输出里就只有一个SELECT,这样一来每一行在这个列上都会显示一个1。如果语句中使用了子查询、集合操作、临时表等情况,会给ID列带来很大的复杂性。如上例中,WHERE部分使用了子查询,其id=2的行表示一个关联子查询。

select_type

语句所使用的查询类型。是简单SELECT还是复杂SELECT(如果是后者,显示它属于哪一种复杂类型)。常用有以下几种标记类型。

  • DEPENDENT SUBQUERY

子查询内层的第一个SELECT,依赖于外部查询的结果集。

  • DEPENDENT UNION

子查询中的UNION,且为UNION中从第二个SELECT开始的后面所有SELECT,同样依赖于外部查询的结果集。

  • PRIMARY

子查询中的最外层查询,注意并不是主键查询。

  • SIMPLE

除子查询或UNION之外的其他查询。

  • SUBQUERY

子查询内层查询的第一个SELECT,结果不依赖于外部查询结果集。

  • UNCACHEABLE SUBQUERY

结果集无法缓存的子查询。

  • UNION

UNION语句中的第二个SELECT开始后面的所有SELECT,第一个SELECT为PRIMARY。

  • UNION RESULT

UNION中的合并结果。从UNION临时表获取结果的SELECT。

  • DERIVED

衍生表查询(FROM子句中的子查询)。MySQL会递归执行这些子查询,把结果放在临时表里。在内部,服务器就把当做一个"衍生表"那样来引用,因为临时表就是源自子查询。

table

这一步所访问的数据库中表的名称或者SQL语句指定的一个别名表。这个值可能是表名、表的别名或者一个为查询产生的临时表的标识符,如派生表、子查询或集合。

type

表的访问方式。以下列出了各种不同类型的表连接,依次是从最好的到最差的。

  • system

系统表,表只有一行记录。这是const表连接类型的一个特例。

  • const

读常量,最多只有一行匹配的记录。由于只有一行记录,优化程序里该行记录的字段值可以被当作是一个恒定值。const用于在和PRIMARY KEY或UNIQUE索引中有固定值比较的情形。

  • eq_ref

最多只会有一条匹配结果,一般是通过主键或唯一键索引来访问。从该表中会有一行记录被读取出来以和从前一个表中读取出来的记录做联合。与const类型不同的是,这是最好的连接类型。它用在索引所有部分都用于做连接并且这个索引是一个PRIMARY KEY或UNIQUE类型。eq_ref可以用于在进行"="做比较时检索字段。比较的值可以是固定值或者是表达式,表达示中可以使用表里的字段,它们在读表之前已经准备好了。

  • ref

JOIN语句中驱动表索引引用的查询。该表中所有符合检索值的记录都会被取出来和从上一个表中取出来的记录作联合。ref用于连接程序使用键的最左前缀或者是该键不是PRIMARY KEY或UNIQUE索引(换句话说,就是连接程序无法根据键值只取得一条记录)的情况。当根据键值只查询到少数几条匹配的记录时,这就是一个不错的连接类型。ref还可以用于检索字段使用"="操作符来比较的时候。

  • ref_or_null

与ref的唯一区别就是在使用索引引用的查询之外再增加一个空值的查询。这种连接类型类似ref,不同的是MySQL会在检索的时候额外的搜索包含NULL值的记录。这种连接类型的优化是从MySQL 4.1.1开始的,它经常用于子查询。

  • index_merge

查询中同时使用两个(或更多)索引,然后对索引结果进行合并(merge),再读取表数据。这种连接类型意味着使用了Index Merge优化方法。

  • unique_subquery

子查询中的返回结果字段组合是主键或唯一约束。

  • index_subquery

子查询中的返回结果字段组合是一个索引(或索引组合),但不是一个主键或唯一索引。这种连接类型类似unique_subquery。它用子查询来代替IN,不过它用于在子查询中没有唯一索引的情况下。

  • range

索引范围扫描。只有在给定范围的记录才会被取出来,利用索引来取得一条记录。

  • index

全索引扫描。连接类型跟ALL一样,不同的是它只扫描索引树。它通常会比ALL快点,因为索引文件通常比数据文件小。MySQL在查询的字段知识单独的索引的一部分的情况下使用这种连接类型。

  • fulltext

全文索引扫描。

  • all

全表扫描。

possible_keys

该字段是指MySQL在搜索表记录时可能使用哪个索引。如果没有任何索引可以使用,就会显示为null。

key

查询优化器从possible_keys中所选择使用的索引。key字段显示了MySQL实际上要用的索引。当没有任何索引被用到的时候,这个字段的值就是NULL。

key_len

被选中使用索引的索引键长度。key_len字段显示了MySQL使用索引的长度。当key字段的值为NULL时,索引的长度就是NULL。

ref

列出是通过常量,还是某个表的某个字段来过滤的。ref字段显示了哪些字段或者常量被用来和key配合从表中查询记录出来。

rows

该字段显示了查询优化器通过系统收集的统计信息估算出来的结果集记录条数。

Extra

该字段显示了查询中MySQL的附加信息。

filtered

这个列式在MySQL5.1里新加进去的,当使用EXPLAIN EXTENDED时才会出现。它显示的是针对表里符合某个条件(WHERE子句或联接条件)的记录数的百分比所作的一个悲观估算。

3) SQL改写

EXPLAIN除了可以显示执行计划外,还可以显示SQL改写。所谓SQL改写,是指MySQL在对SQL语句进行优化前,会基于一些原则进行语句的改写,以方便后面的优化器进行优化生成更优的执行计划。该功能是通过EXPLAIN EXTENDED+SHOW WARNINGS配合使用。下面通过示例说明一下。
在这里插入图片描述
从上面示例中,可看到原有语句中的IN子查询被改写成为表间关联的方式。

2、统计信息

查看统计信息也是优化语句中必不可少的一步。通过统计信息可以快速了解对象的存储特征如何。下面说明主要的两类统计信息——表、索引。

1) 表统计信息 — SHOW TABLE STATUS

在这里插入图片描述

  • Name:表名

  • Engine:表的存储引擎类型(ISAM、MyISAM或InnoDB)

  • Row_format:行存储格式(Fixed-固定的、Dynamic-动态的或Compressed-压缩的)

  • Rows:行数量。在某些存储引擎中,例如MyISAM和ISAM他们存储了精确的记录数。不过其他存储引擎中,它可能只是近似值。

  • Avg_row_length:平均行长度。

  • Data_length:数据文件的长度。

  • Max_data_length:数据文件的最大长度。

  • Index_length:索引文件的长度。

  • Data_free:已分配但未使用了字节数。

  • Auto_increment:下一个autoincrement(自动加1)值。

  • Create_time:表被创造的时间。

  • Update_time:数据文件最后更新的时间。

  • Check_time:最后对表运行一个检查的时间。执行mysqlcheck命令后更新,仅对MyISAM有效。

  • Create_options:额外留给CREATE TABLE的选项。

  • Comment:当创造表时,使用的注释(或为什么MySQL不能存取表信息的一些信息)。

  • Version:数据表的’.frm’文件版本号。

  • Collation:表的字符集和校正字符集。

  • Checksum:实时的校验和值(如果有的话)。

3、索引统计信息 — SHOW INDEX

在这里插入图片描述

  • Table:表名。

  • Non_unique:0,如果索引不能包含重复。

  • Key_name:索引名

  • Seq_in_index:索引中的列顺序号,从1开始。

  • Column_name:列名。

  • Collation:列怎样在索引中被排序。在MySQL中,这可以有值A(升序)或NULL(不排序)。

  • Cardinality:索引中唯一值的数量。

  • Sub_part:如果列只是部分被索引,索引字符的数量。当整个字段都做索引了,那么它的值是NULL。

  • Packed:表示键值是如何压缩的,NULL表示没有压缩。

  • Null:当字段包括NULL的记录是YES,它的值为,反之则是’’。

  • Index_type:使用了哪种索引算法(有BTREE、FULLTEXT、HASH、RTREE)。

  • Comment:备注。

  • 系统参数:系统参数也会影响语句的执行效率。查看系统参数,可使用SHOW VARIABLES命令。

1) 参数说明

系统参数很多,下面介绍几个。

sort_buffer_size

排序区大小。其大小直接影响排序使用的算法。如果系统中排序都比较大、内存充足且并发量不是很大的情况,可以适当增加此参数。这个参数是针对单个Thead的。

join_buffer_size

Join操作使用内存区域大小。只有当Join是ALL、index、range或index_merge时使用到Join Buffer。如果join语句较多,可以适当增大join_buffer_size。需要注意到是,这个值针对单个Thread。每个Thread都会自己创建独立的Buffer,而不是整个系统共享的Buffer,不要设置过大而造成系统内存不足。

tmp_table_size

如果内存内的临时表超过该值,MySQL自动将它转换为硬盘上的MyISAM表。如果执行许多高级GROUP BY查询并且有大量内存,则可以增加tmp_table_size的值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值