背景
最近领导分配了个任务,测试sit环境一些功能相比之前慢了许多,需要优化一下。
问题排查过程
浏览器F12查看相关接口的响应,看到底是哪个接口反应慢,根据互联网的要求,页面3秒还没有显示出来,用户体验会非常差。
查看相关代码的提交时间,这些代码一上线就没有改动过,由此以我三年职业生涯的经验推断,可能是接口相关数据库表设计不合理或者需要优化导致的问题,因而该篇文章由此诞生!
数据库单表优化步骤
设计表时:1.选择合适的字段类型
2.创建高性能索引
运维期间: 1.慢sql优化
2.mysql参数调优
3.数据碎片与索引碎片优化
之前我已做过数据库部分优化,今天我们所采用的的优化方案是:数据碎片与索引碎片优化
Q:为什么会产生数据碎片与索引碎片呢?
A:由于表记录delete后,只是在相应记录上表示该记录被删除出,表空间没有释放从而导致数据碎片和索引碎片,占用服务器存储空间和影响索引的效率。
mysql引擎:
MyISAM引擎: 数据储存在MYD文件中,索引储存在MYI文件中
InnoDB引擎:frm文件存储表结构,idb文件储存索引和数据
数据碎片优化步骤
查看ide库下需要优化的相关表sql:
select table_name,data_free from information_schema.tables where table_schema='ide' order by a.data_free desc;可以看到每个表的数据碎片分别是多少,如图所示:
我们可以看到:rdos_engine_job_cache表的数据碎片比较多,可以清理一下
查看清理前表相关文件的大小,数据和索引文件是49452,如图所示:
也可以用sql查询:数据大小如上上图的data_length,和data_free之和。
索引大小:show index from rdos_engine_job_cache;
Cardinality:索引中唯一值的数目的估计值。通过运行ANALYZE TABLE或myisamchk -a可以更新。基数根据被存储为整数的统计数据来计数,所以即使对于小型表,该值也没有必要是精确的。基数越大,当进行联合时,MySQL使用该索引的机会就越大。
相关字段值老铁们可以自行百度。
注意:在OPTIMIZE TABLE运行过程中,MySQL会锁定表。
对于myisam可以直接使用 optimize table table.name, 当是InnoDB引擎时,会报“Table does not support optimize, doing recreate + analyze instead”,一般情况下,由myisam转成innodb,会用alter table table.name engine='innodb'进行转换,优化也可以用这个。所以当是InnoDB引擎时我们就用alter table table.name engine='innodb'来代替optimize做优化就可以。
我们的表用的是Innodb引擎,执行命令:alter table rdos_engine_job_cache engine='innodb';如图所示:
由图可以看到清理前后的对比:表空间确实释放了不少
索引碎片优化步骤
Analyze Table
MySQL 的Optimizer(优化元件)在优化SQL语句时,首先需要收集一些相关信息,其中就包括表的cardinality(可以翻译为“散列程度”),它表示某个索引对应的列包含多少个不同的值——如果cardinality大大少于数据的实际散列程度,那么索引就基本失效了。
我们可以使用SHOW INDEX语句来查看索引的散列程度:
SHOW INDEX FROM PLAYERS;
TABLE KEY_NAME COLUMN_NAME CARDINALITY
------- -------- ----------- -----------
PLAYERS PRIMARY PLAYERNO 14
因为此时PLAYER表中不同的PLAYERNO数量远远多于14,索引基本失效。
下面我们通过Analyze Table语句来修复索引:
ANALYZE TABLE PLAYERS;
SHOW INDEX FROM PLAYERS;
结果是:
TABLE KEY_NAME COLUMN_NAME CARDINALITY
------- -------- ----------- -----------
PLAYERS PRIMARY PLAYERNO 1000
此时索引已经修复,查询效率大大提高。
需要注意的是,如果开启了binlog,那么Analyze Table的结果也会写入binlog,我们可以在analyze和table之间添加关键字local取消写入。