概要回顾

之前看过《高性能mysql》对mysql数据库有了系统化的理解,虽然没能达到精通,但有了概念,遇到问题时会有逻辑条理的分析;

这回继上次sql分析结果的一个继续延伸分析,我拿了;

备注:分析(除sql基本优化过程外)这个过程并定位到具体问题,给出针对性的解决方案,是一个非常漫长的过程,需要一个个的去排除和论证的过程;当对来说十分枯燥和窘境,但成功了就是一非常大的收获和经验;

-- ③ 优化前
select p.record_data,p.cooperation_name,p.cooperation_id,p.block_time,p.oss_volume as userOSSCapacity,p.txhash,p.seq_id,p.pre_seq_id,p.custom_string FROM poehistoryinfo p LEFT JOIN recordregistryinfo r ON p.record_registry_info_id=r.id LEFT JOIN identityinfo i ON i.account_id=r.mgmt_account_id where r.contract_address=? GROUP BY r.contract_address,p.record_data,p.cooperation_name,p.cooperation_id,p.block_time,p.txhash,p.seq_id,p.pre_seq_id,p.custom_string,p.oss_volume ORDER BY p.block_time DESC limit ?,? -- ③ 优化后
SELECT p.record_data,p.cooperation_name,p.cooperation_id,p.block_time,p.oss_volume as userOSSCapacity,p.txhash,p.seq_id,p.pre_seq_id,p.custom_string FROM poehistoryinfo p INNER JOIN
(SELECT p1.id FROM poehistoryinfo p1 LEFT JOIN recordregistryinfo r ON p1.record_registry_info_id=r.id LEFT JOIN identityinfo i ON i.account_id=r.mgmt_account_id where r.contract_address=? ORDER BY p1.block_time DESC limit ?,?) a ON a.id = p.id ;
--- 环境RDS 1C 1G mysql数据库,导入数据库,这时没有其他多余的IO读写操作
这回我申请了一个RDS 1C 1G mysql数据库,导入数据库,这时没有其他多余的IO读写操作;
效果:2条sql语句,
①优化前sql, 5.77ms
②优化后sql, 0.01ms 执行计划正常 --- 环境ECS 1C 1G自建数据库这是没有多余操作,这时没有其他多余的IO读写操作
ECS 自建数据库 1C 1G 这是没有多余操作,
效果:2条sql语句,
①优化前sql, 1.77ms
②优化后sql, 0.01ms 执行计划正常 --- 环境RDS 1C 1G mysql数据库,线上库,这时IOPS平均操作为300~400之间
我司生产上RDS 1C 1G 这时平均读写操作为300-400;
效果:2条sql语句,
①优化前sql, 5.89ms
②优化后sql, 6.35ms,不正常

问题

按mysql语句优化原则优化之后发现未达到预想的效果,问题如下:

  1. 在不优化的情况下自建数据库执行③slq语句比RDS数据库要快5倍以上;
  2. 优化之后的sql语句放到RDS上,比之前未优化的sql语句还慢;

分析思路

为了发现问题所以,我获取RDS 上的sql执行计划:

mysql> explain select p.record_data,p.cooperation_name,p.cooperation_id,p.block_time,p.oss_volume as userOSSCapacity,p.txhash,p.seq_id,p.pre_seq_id,p.custom_string FROM poehistoryinfo p LEFT JOIN recordregistryinfo r ON p.record_registry_info_id=r.id LEFT JOIN identityinfo i ON i.account_id=r.mgmt_account_id  where r.contract_address='85b692c81d16bfa49ce0b8a166458c71f522fd5b' GROUP BY r.contract_address,p.record_data,p.cooperation_name,p.cooperation_id,p.block_time,p.txhash,p.seq_id,p.pre_seq_id,p.custom_string,p.oss_volume ORDER BY p.block_time DESC limit 1,25;
id FROM poehistoryinfo p1 LEFT JOIN recordregistryinfo r ON p1.record_registry_info_id=r.id LEFT JOIN identityinfo i ON i.account_id=r.mgmt_account_id where r.contract_address='85b692c81d16bfa49ce0b8a166458c71f522fd5b' ORDER BY p1.block_time DESC limit 1,25;
+----+-------------+-------+------------+------+-----------------------------+-----------------------------+---------+------------------------+--------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+-----------------------------+-----------------------------+---------+------------------------+--------+----------+----------------------------------------------------+
| 1 | SIMPLE | r | NULL | ALL | PRIMARY | NULL | NULL | NULL | 39 | 10.00 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | i | NULL | ref | identityinfo_account_id_ind | identityinfo_account_id_ind | 153 | sync.r.mgmt_account_id | 1 | 100.00 | Using where; Using index |
| 1 | SIMPLE | p | NULL | ALL | NULL | NULL | NULL | NULL | 172999 | 10.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+-----------------------------+-----------------------------+---------+------------------------+--------+----------+----------------------------------------------------+
3 rows in set, 1 warning (0.01 sec)
mysql> explain SELECT p.record_data,p.cooperation_name,p.cooperation_id,p.block_time,p.oss_volume as userOSSCapacity,p.txhash,p.seq_id,p.pre_seq_id,p.custom_string FROM poehistoryinfo p  INNER JOIN (SELECT p1.id FROM poehistoryinfo p1 LEFT JOIN recordregistryinfo r ON p1.record_registry_info_id=r.id LEFT JOIN identityinfo i ON i.account_id=r.mgmt_account_id  where r.contract_address='85b692c81d16bfa49ce0b8a166458c71f522fd5b' ORDER BY p1.block_time DESC limit 1,25) a ON a.id = p.id ;

+----+-------------+------------+------------+--------+-----------------------------+-----------------------------+---------+------------------------+--------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+--------+-----------------------------+-----------------------------+---------+------------------------+--------+----------+----------------------------------------------------+
| 1 | PRIMARY | <derived2> | NULL | ALL | NULL | NULL | NULL | NULL | 26 | 100.00 | NULL |
| 1 | PRIMARY | p | NULL | eq_ref | PRIMARY | PRIMARY | 4 | a.id | 1 | 100.00 | NULL |
| 2 | DERIVED | r | NULL | ALL | PRIMARY | NULL | NULL | NULL | 39 | 10.00 | Using where; Using temporary; Using filesort |
| 2 | DERIVED | i | NULL | ref | identityinfo_account_id_ind | identityinfo_account_id_ind | 153 | sync.r.mgmt_account_id | 1 | 100.00 | Using where; Using index |
| 2 | DERIVED | p1 | NULL | ALL | NULL | NULL | NULL | NULL | 172999 | 10.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+------------+------------+--------+-----------------------------+-----------------------------+---------+------------------------+--------+----------+----------------------------------------------------+
5 rows in set, 1 warning (0.00 sec)

根据上面的分析和上篇ECS sql执行计划结果比较差别如下:

  1. ECS ③优化前 sql 与 RDS ③优化前 执行计划结果无很大差异,但执行结果返回的时间分别是0.47 sec 和 5.77 sec(unbelievable);
  2. ECS ③优化后 sql 与 RDS ③优化后 执行计划结果相差非常大;
    1. ECS ③优化后 sql Extra : Using where(索引);Using index, rows 最大259行等
    2. RDS ③优化后 sql Extra : 比较多Using where;Using temporary;Using filesort;Using where;Using index;Using buffer(Block Nested Loop); rows 中有172999(相当于全表查询) 

分析术语名词说明

Using index:表示MySQL将使用覆盖索引
Using where: 表示使用存储引擎检索索引在进行过滤
Using temporary: 表示MySQL对查询结果排序时会使用一个临时表
Using filesort: 表示Mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取
Using buffer(Block Nested Loop): 关联嵌套查询

分析以上结果,很明显RDS 优化后的效果非常不佳,甚至RDS优化前还差,使用时间还长; 而优化语句是按照Mysql 优化器和索引的基本原则来的,除非是唯一能想到的是两个mysql环境与配置存在差异导致的。 按照这个思路,结合RDS工单处理工程师, 去查询语句如下

  • show profiles;
  • show global variables like '%query_cache%';
  • show variables like '%optimizer_switch%' \G;
  • show create table 表明 \G;
  • show variables;

step 1:分析show profiles,发现主要耗时时间在sending data上,但无法定位,猜测可能是缓存或者是乐观锁之类的问题;

step 2:分析%query_cache%发现query_cache是没有开启的;

step 3:分析table表是否存在差异,貌似没有...排除

step 4:分析show variables;猜测rds的"tmpdir","/home/mysql/data3001/tmp",ecs自建的是| tmpdir | /tmp 会对Using temporary; Using filesort 操作有影响;怀疑/tmp 是属于内存盘,所以ECS会比RDS性能更优,但当我用df -h 看一下,发现并没有这种情况,再由RDS工程师查看ubuntu文档对其验证,发现假设不成立;

step 5: 之前是试过使用强制索引来改变优化后的sql语句的执行计划,但并没有多大的用处。RDS工程师分析认为问题出在IOPS(Input/Output Operations Per Second)上,因为RSD平均IOPS有300-400,而ECS则是0;为了排除这个原因RDS工程师很大方的建了一个1C1G RDS MySQL给我测试使用。优化后的问题不在出现,而优化前的SQL语句还是有问题:ECS的执行时间比RDS的块10多倍;

不过有一点可以确定,但重复执行多次sql语句时,执行返回结果时间会缩短,一直到一个基本固定不变的值,这说明查询存在缓存, 目前给出的解决方案是修改RDS配置如下:

set tmp_table_size=50*1024*1024*2;
set max_heap_table_size=50*1024*1024*2;
set join_buffer_size=50*1024*1024;
set sort_buffer_size=50*1024*1024;

其实,我认为这个语句无论是否有效,对RDS的用户而言都是非常差的一个表现,还需要认为的去深度考虑mysql的配置参数变量,从某种意义上说就是DB owner,那我们又何必要使用RDS呢。

后来发现 到了公司生产环境上修改配置时反而干慢了,后来一同事针对IOPS 数值不正常情况做了深度排查,发现xxxx系统上有一个定时任务,该定时任务每隔3秒执行一次,而且是针对600多万数据的非索引全表扫描,耗时已经大于3秒,(导致上一次还没执行完,变又开始下一轮的执行) ,不过定时任务用的是SpringBoot下Quartz的集成框架,其中有一共能是要等上一次任务执行完毕才可以继续下一次任务执行;这也就意味着每时每刻Mysql都有全盘扫描操作,这也是导致Mysql IOPS 居高不下的原因;

后来给出的解决方案是将该查询语句添加索引,直接让IOPS 从300-800 降到了30左右;整体性能提高;之前的条件语句优化查询也回到了正常范围;

从这点我们可以看出在Mysql中 IOPS的高低直接影响SQL 语句的性能查询与优化;

mysql性能优化分析 --- 下篇的更多相关文章

  1. mysql性能优化分析 --- 上篇

    概要 之前看过<高性能mysql>对mysql数据库有了系统化的理解,虽然没能达到精通,但有了概念,遇到问题时会有逻辑条理的分析; 问题 问题:公司xxx页面调用某个接口时,loading ...

  2. mysql性能优化-慢查询分析、优化索引和配置 (慢查询日志,explain,profile)

    mysql性能优化-慢查询分析.优化索引和配置 (慢查询日志,explain,profile) 一.优化概述 二.查询与索引优化分析 1性能瓶颈定位 Show命令 慢查询日志 explain分析查询 ...

  3. Mysql - 性能优化之子查询

    记得在做项目的时候, 听到过一句话, 尽量不要使用子查询, 那么这一篇就来看一下, 这句话是否是正确的. 那在这之前, 需要介绍一些概念性东西和mysql对语句的大致处理. 当Mysql Server ...

  4. Mysql性能优化三(分表、增量备份、还原)

    接上篇Mysql性能优化二 对表进行水平划分 如果一个表的记录数太多了,比如上千万条,而且需要经常检索,那么我们就有必要化整为零了.如果我拆成100个表,那么每个表只有10万条记录.当然这需要数据在逻 ...

  5. mysql 性能优化方向

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...

  6. MySQL性能优化总结

    一.MySQL的主要适用场景 1.Web网站系统 2.日志记录系统 3.数据仓库系统 4.嵌入式系统 二.MySQL架构图: 三.MySQL存储引擎概述 1)MyISAM存储引擎 MyISAM存储引擎 ...

  7. MYSQL性能优化的最佳20+条经验

    MYSQL性能优化的最佳20+条经验 2009年11月27日 陈皓 评论 148 条评论  131,702 人阅读 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数 ...

  8. mysql 性能优化方案

    网 上有不少MySQL 性能优化方案,不过,mysql的优化同sql server相比,更为麻烦与复杂,同样的设置,在不同的环境下 ,由于内存,访问量,读写频率,数据差异等等情况,可能会出现不同的结果 ...

  9. mysql 性能优化方案1

    网 上有不少mysql 性能优化方案,不过,mysql的优化同sql server相比,更为麻烦与复杂,同样的设置,在不同的环境下 ,由于内存,访问量,读写频率,数据差异等等情况,可能会出现不同的结果 ...

随机推荐

  1. Neutron Vlan Network 学习

    vlan network 是带 tag 的网络,是实际应用最广泛的网络类型.    下图是 vlan100 网络的示例.   1. 三个 instance 通过 TAP 设备连接到名为 brqXXXX ...

  2. pycharm中运行时添加配置 及pytest模式怎么修改为run模式

    会发现不是控制台输出,而是pytest模式. 修改: 当运行时,发现无法运行: 然后点击Add Configuration, 点击加号,点击Python: 选择脚本路径和解释器.点击OK即可.

  3. java中定时器的简单使用

    1.首先肯定是容器一启动就要启动定时器,所以我们可以选择把定时器写在一个监听器里,容器一启动所以监听器也就跟着启动,然后定时器就可以工作了. 第一步,把自己写的监听器加到web.xml中: 第二步,写 ...

  4. mysql索引原理

    1.B+Tree 索引的数据结果是B+Tree,它比BTree查询时,以更少的IO次数占优势. 2.聚集索引与非聚集索引 聚集索引:索引的逻辑顺序与磁盘上数据的物理顺序相同.(表中最多只有一个) 比如 ...

  5. 最长公共子序列(POJ1458)

    给出两个字符串,求出这样的一个最长的公共子序列的长度:子序列中的每个字符都能在两个原串中找到,而且每个字符的先后顺序和原串中的先后顺序一致. Sample Input: abcfbc abfcabpr ...

  6. sql 查询字段如果为null 则返回0的写法

    oracle select nvl(字段名,0) from 表名; ----------------------------------- sqlserver select isnull(字段名,0) ...

  7. Java进程通信之映像文件共享内存

    Java进程通信之映像文件共享内存 1. 共享内存 vs 进程通信 对UNIX系统来说,共享内存分为一般共享内存和映像文件共享内存两种.但windows实际上只有影像文件共享内存一种. 而说到进程通信 ...

  8. Day 1 上午

    唉,上午就碰到一个开不了机的电脑,白白浪费了半个小时,真的难受QwQ POINT1 枚举 枚举也称作穷举,指的是从问题所有可能的解的集合中一一枚举各元素. 用题目中给定的检验条件判定哪些是无用的,哪些 ...

  9. ASP.Net笔记整理(一)

    验证码类 using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Draw ...

  10. Linux lvs-DR模式配置详解

    本篇文档主要是记录DR模式实现过程,以及各配置步骤的原理.“lvs三种模式工作原理”中描述了LVS的NAT.DR.TUN三种模式的工作原理. DR模式是通过director将报文源和目标MAC地址修改 ...