Mysql性能测试主要内容
相信很多做性能测试的朋友都知道,性能测试并不单单只是看服务器cpu、IO、内存、网络等,我们还需要了解Mysql性能,那么我们看看Mysql性能主要内容有哪些呢?
MySql数据库介绍
Mysql相信大家做测试的,都非常的了解了。它的发展过程其实我们的关系并不大,之所以介绍Mysql是因为现在他是一个主流的数据库,大多数功能目前都在用Mysql。这里主要是想跟大家介绍一下MariaDb,那我们来看一下MariDb到底是什么?
mysql主流分支-MariDb
MariaDB的主要创建者是Monty Widenius,也是MySQL的初始创建者。Monty成立了一家名为Monty Program的公司来管理MariaDB的开发,这家公司雇佣开发人员来编写和改进MariaDB产品。这既是一件好事,也是一件坏事:有利的一面在于他们是Maria功能和bug修复的佼佼者,但公司不是以赢利为目的,而是由产品驱动的,这可能会带来问题,因为没有赢利的公司不一定能长久维持下去。
这里之所以说到MariDb,是希望大家之后看到,对于这个有一定的了解,因为现在MariDb已经成为MySql的主流分支,目前也越来越多的公司在使用它。其实它很mysql差不多几乎一样,是基于mysql的,对于使用者而言,是无感知的。
MariDb的特点:
- mysql之父Widenius创建,目标在于替换现有mysql
- 兼容mysql,对于开发者无感知不到变化
- MariaDB is free and open source software(MariaDB是开源的)
MySql数据库监控之重点监控指标
其实mysql的指标是非常多的,这里我只记录了一些我们平时重点需要关注的指标哦~
QPS (queries per seconds): 每秒钟查询数量
计算方法:queries / secondes 查询总数 除以 秒数
我们可以在mysql的终端去执行如下命令查看QPS,相信这里大家会有疑惑,现在市面上有很多工具,可以去查看mysql的性能指标,为什么还需要单独去执行命令查看?
其实不管是什么监控工具,他们的底层工作原理都是相同的,他们都是通过这些命令去获取这些指标的,这样就相当于我们了解了工具中那么底层具体是怎么去执行的。
show global status like 'Question%';
TPS (Tranaction pre senconds): 每秒的事务数
TPS = (Com_commit + Com_rollback) / seconds :提交次数 + 回滚次数 / 秒数
// 查看Com_commit 和 Com_rollback的命令
show global status like 'Com_commit';
show global status like ' Com_rollback';
线程连接数
// 使用最大连接数
show global status like ' Max_userd_connections';
// 线程连接数
show global status like 'Threads%';
// 设置的最大连接数
show variables like 'Max_connections';
Query Cache 查询缓存
- 查询缓存用于缓存select查询结果
- 当下接收到相同的查询请求时,不再执行实际查询处理而直接返回结果
- 适用于大量查询数据,很少改变查询结果
怎么样开启query cache?
- 修改my.cnf文件
- 将query_cache_size设置为具体的大小,具体的大小是多少取决于查询的实际情况,但最好设置为1024的倍数,参考值32M。当然这个大小是可以通过返回的性能测试进行调节,找到最适合的值。
- 增加一行:query_cache_type=0 /1 / 2
- 如果设置1,将会缓存所有的查询结果,除非你select语句使用SQL_NO_CACHE禁用了查询缓存
- 如果设置2,则只缓存在select语句中通过SQL_CACHE指定需要缓存的查询
注意:在调整query cache的时候,我们需要跟开发开发沟通我们具体开启什么样的类型,然后开发在实际操作的时候是否加上还是不加上SQL_CACHE。
查询Query Cache命中率
show status like ' Qcache%';
// Query Cache命中率计算
Query_cache_hits = (Query_hits/ (Query_hits + Qcache_inserts))* 100%;
// 查看锁
show global status like '%lock';
Table_locks_waited/Table_locks_immediate // 值越大代表锁造成的阻塞越严重
Innodb_row_lock_waits innodb // 行锁,太大可能是间隙锁造成的
主从延时
// 查询主从延时的时间
show slave status
mysql慢查询
什么是慢查询呢?
当我第一次接触到慢查询,以为是比较慢的查询语句,但是当时想着,怎么会有这么low的解释呢?后面一了解,还真是。
慢查询其实指的是查询比较慢的sql语句。那么我们怎么去定义这个慢查询呢?
- 执行速度超过定义时间的查询
- 不同的系统定义不同的慢查询指标
其实相信大家看到这个慢查询的定义,都会有个疑惑,怎么样去定义执行速度多久才算慢呢?其实不同的操作系统,以及不同的业务类型,他们去定义慢查询的指标也是不同的,这个需要我们根据实际的业务场景去定义。那么我们接下来看一下,如果开启慢查询呢?
开启慢查询:
- 编辑/ect/my.cnf, 在[mysqlId]域中添加;
- 开启慢查询:show_query_log = 1
- 慢查询日志路径:show_query_log_file=/data/mysql/show.log(路径是自己定义的,然后需要注意的是,启动mysql数据的用户,需要有写入的权限)
- 慢查询的时长:long_query_time = 1
- 设置下方数据,未使用索引的查询也被记录到慢查询的日志中, log_queries_not_using_indexes = 1
当我们知道慢查询查看日志其实就是一个文件,那么我们可以使用mysqldumpslow命令进行慢查询日志分析。mysqldumpslow是MySQL自带的,无需安装。
mysqldumpslow命令
-s:是表示按照何种方式排序
-t:是top n的意思,即为返回前面多少条数据
-g:后边可以写一个正则匹配模式,大小写不敏感
mysqldumpslow -s 更多参数
c : 访问技术
l: 锁定时间
r: 返回数据
t:查询时间
al:平均锁定时间
ar:平均返回记录数
at: 平均参数时间
得到返回记录集最多的10个sql
// 得到返回记录集最多的10个sql
mysqldumpslow -s -r -t 10 slow.log
// 得到访问次数最多的10个sql
mysqldumpslow -s c -t 10 slow.log
// 得到按时间顺序排序的前10条里面包含有左连接的查询语句
mysqldumpslow -s t -t 10 -g "left join" slow.log
sql语句性能分析
用法:explain select 语句 Explain查看执行计划
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈
1、能干嘛
- 表的读取顺序
- 数据读取操作的操作类型
- 哪些索引可以使用
- 哪些索引被实际使用
- 表之间的引用
- 每张表有多少行被优化器查询
2、用法:Explain + SQL语句
3、执行计划包含的信息
4、各字段解释(id、type、key、rows、Extra是衡量指标)
id:select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的 顺序三种情况:
- id相同,执行顺序由上至下
- id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
- id相同不同,同时存在:id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行,下图中表示衍生表s1表,derived2的2代表id=2
select_type:查询的类型,主要是用于区别普通查询、联合查询、子查询等的复杂查询
SIMPLE:简单的 select 查询,查询中不包含子查 PRIMARY:查询中若包含任何复杂的子部分,最外层查询则被标记为 SUBQUERY:在SELECT或WHERE列表中包含了子查询 DERIVED:在FROM列表中包含的子查询被标记为DERIVED(衍生),MySQL会递归执行这些子查询, 把结果放在临时表里 UNION:若第二个SELECT出现在UNION之后,则被标记为UNION;若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED UNION RESULT:从UNION表获取结果的SELECT
table:显示这一行的数据是关于哪张表的
type:访问类型排列,显示查询使用了何种类型,结果值从最好到最坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
- system:表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个也可以忽略不计 const:表示通过索引一次就找到了,const用于比较primary key或者unique索引。因为只匹配一行数据, 所以很快如将主键置于where列表中,MySQL就能将该查询转换为一个常量
- eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描
- ref:非唯一性索引扫描,返回匹配某个单独值的所有行.本质上也是一种索引访问,它返回所有匹配某个 单独值的行,然而,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体
- range:只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引一般就是在你的where语 句中出现了between、<、>、in等的查询这种范围扫描索引扫描比全表扫描要好,因为它只需要开 始于索引的某一点,而结束语另一点,不用扫描全部索引。
- index:Full Index Scan,index与ALL区别为index类型只遍历索引树。这通常比ALL快,因为索引文件通 常比数据文件小。(也就是说虽然all和Index都是读全表,但index是从索引中读取的,而all是从 硬盘中读的)
- all:Full Table Scan,将遍历全表以找到匹配的行 一般来说,得保证查询至少达到range级别,最好能达到ref。
- const: where id = 1 id是写死的常量id只有一条 性能好
8) eq_ref: where t1.id = t2.id t2.id只有一条记录 t2表中只有一条记录 t2是全表扫
9) ref: where col1 = ‘ac’ ac是常量,但是col1是非唯一性索引,找到非唯一性索引的全部行
10) rang:
11) index:
12)all: where条件字段没建立索引,或者索引失效
possible_keys : 显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用
key : 实际使用的索引。如果为NULL,则没有使用索引;
查询中若使用了覆盖索引,则该索引仅出现在key列表中:select 查询的字段个数、顺序和复合索引的字段的个数、顺序一一符合
key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。在不损失精确性的情况下,长度越短越好,key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的
ref:显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值
由key_len可知t1表的idx_col1_col2被充分使用,col1匹配t2表的col1,col2匹配了一个常量,即 ‘ac’
rows:根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数
建立索引之前和建立索引之后,找出记录所需要的行数对比
Extra:包含不适合在其他列中显示但十分重要的额外信息(前三个最重要:Using filesort、Using temporary表明语句烂需要优化,Using index表明语句还不错)
Using filesort :说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。 MySQL中无法利用索引完成的排序操作称为“文件排序”
索引顺序是col1、col2、col3,where用到col1 ,order by用到col3但是,但是中间少了col2
索引顺序是col1、col2、col3,where用到col1 ,order by用到col2 、col3
Using temporary:使了用临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。
索引顺序是col1、col2,group by跨过col1用col2
索引顺序是col1、col2,group by按顺序使用col1、col2
Using index:表示相应的select操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错!如果同时出现using where,表明索引被用来执行索引键值的查找;如果没有同时出现using where,表明索引用来读取数据而非执行查找动作。
覆盖索引(Covering Index):就是select的数据列只用从索引中就能够取得,不必读取数据行,MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件,换句话说查询列要被所建的索引覆盖。
Using where:表明使用了where过滤
Using join buffer:使用了连接缓存:
impossible where:where子句的值总是false,不能用来获取任何元组 where name = ‘1’ and name = ‘2’
select tables optimized away:在没有GROUP BY子句的情况下,基于索引优化MIN/MAX操作或者对于MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段再进行计算,查询执行计划生成的阶段即完成优化。
distinct:优化distinct操作,在找到第一匹配的元组后即停止找同样值的动作
例子:
- 第一行(执行顺序4):id列为1,表示是union里的第一个select,select_type列的primary表 示该查询为外层查询,table列被标记为,表示查询结果来自一个衍生表,其中derived3中3代表该查询衍生自第三个select查询,即id为3的select。【select d1.name…】
- 第二行(执行顺序2):id为3,是整个查询中第三个select的一部分。因查询包含在from中,所以为derived。【select id,name from t1 where other_column=’’】
- 第三行(执行顺序3):select列表中的子查询select_type为subquery,为整个查询中的第二个select。【select id from t3】
- 第四行(执行顺序1):select_type为union,说明第四个select是union里的第二个select,最先执行【select name,id from t2】
- 第五行(执行顺序5):代表从union的临时表中读取行的阶段,table列的<union1,4>表示用第一个和第四个select的结果进行union操作。【两个结果union操作】
MySql慢查询的工作原理及操作
未完待续…