MySQL优化案例(二)
这是学习笔记的第 1979 篇文章
近期收到慢日志监控报警,在慢日志平台查看,主要瓶颈在于几条创建临时表的SQL语句,占用了大量的临时空间,需要优化。
SQL语句为:
create temporary table `tem_expireClassID` ( select distinct class_id from dic_fsm_map_relation where game_id = 1 and state = 0 and class_id not in ( SELECT distinct json_extract(fsm_info,'$.FSM.ClassID') FROM dic_fsm_info where state = 0 and json_extract(fsm_info,'$.FSM.ETime') > unix_timestamp(now()) ) order by class_id;
两个表的数据量都在几千条,其实不算多,但是执行时间却差很多。
执行时间为150秒左右。
执行计划为:
+----+--------------------+----------------------+------------+------+---------------+------+---------+------+------+----------+------------------------------+
系统层优化:
系统临时表空间占用150G左右
[[email protected] data]# ll158792155136 May 13 14:40 ibtmp1
经过系统优化和业务协调需要做MySQL实例重启,已重置为初始大小,设置阈值为10G。
SQL层优化
SQL语句的优化分析发现,基于json类型的解析差异和字符类型存在较大的性能差异,建议对json的子查询创建临时表。
测试步骤如下:
create table dic_fsm_info3 (classid varchar(30),etime varchar(30)); --可以根据业务特点创建索引
mysql> insert into dic_fsm_info3 select distinct json_extract(fsm_info,'$.FSM.ClassID') ,json_extract(fsm_info,'$.FSM.ETime') from tgp_db.dic_fsm_info where state=0;
重新执行语句,执行时长优化只0.2秒左右。
select distinct class_id from tgp_db.dic_fsm_map_relation
JSON类型的解析效率可以通过profile的对比方式来分析:
mysql> show profile cpu for query 1;0.047225 | NULL | NULL |0.047196 | NULL | NULL |
而根据字符类型匹配,效率要高两个数量级。
+--------------------+----------+----------+------------+0.000128 | NULL | NULL |0.000001 | NULL | NULL |0.000126 | NULL | NULL |
后续对JSON类型的使用也需要注意以下。