1 如何定位项目中的慢 SQL?
在实际项目中,慢 SQL 的定位通常有两种主流方式:
方式一:使用链路追踪工具(如 SkyWalking)
这个问题,在项目开发中,是非常常见的。 在我们之前的项目中,用到了链路追踪组件 SkyWalking,通过SkyWalking我们就能够知道,所有 请求的调用链路及执行耗时,在显示的报表中,我们就可以看出哪一个接口比较慢,也可以看到这个接口执行过程中,每一个部分的具体耗 时,包括SQL的执行具体时间也都可以看到,通过这个就可以定位慢SQL了。
方式二:开启 MySQL 慢查询日志(Slow Query Log)
那如果在一些项目中,没有用到这类的监控工具,也可以开启MySQL的慢查询日志,通过MySQL的慢查询日志来定位慢SQL。比如:我们可以 在配置文件中配置一下,只要SQL语句的执行耗时超过1秒,我就需要将其记录在慢查询日志中,最终我们只需要通过这份慢查询日志,就能 够知道哪些SQL的执行效率比较低。
2 如何判断 SQL 执行性能及索引是否生效?
这个我们可以借助于MySQL中提供的 explain 关键字,在查询的SQL语句之前,加上explain来查询SQL语句的执行计划。
当然explain查看到的执行计划信息比较多,我们主要关注几个核心指标就可以了。比如:
- 通过 key 、key_len 就能够知道是否命中索引。
- 通过 type 指标,就能知道该SQL的性能怎么样,有没有进一步优化的可能。一定要规避all全表扫描的情况。 type指标性能由好到坏, 依次是:NULL > system > const > eq_ref > ref > range > index > all
- 还需要关注一个指标,就是extra额外的信息。 通过这一项,我们就能够知道,有没有回表查询,有没有涉及到file sort排序。 然后,我们就可以针对 explain 查看到的执行计划,针对于SQL进行优化了。
3 SQL 优化经验总结
表的设计
- 比如数据类型的选择,数值类型到底选择 tinyint、int还是bigint,要根据实际需要选择。字符串类型,到底选择char还是varchar, 也需要根据具体业务确定。(char定长字符串,效率高;varchar变长字符串,效率略低)
- 还需要考虑主键的设计,主键在设计时,尽量考虑递增顺序插入的主键,比如:自增主键 或 雪花算法生成的主键。(这样可以规 避页分裂、页合并现象的产生)
索引的创建
- 针对于数据量较大,且查询比较繁琐的表创建索引。(单表超过10w记录)
- 针对于经常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。
- 尽量选择为区分度高的列建立索引,如果该字段是唯一的,建立唯一索引,效率更高。(区分度越高,效率越高)。
- 在varchar类型的字段上,建议指定索引长度(建立前缀索引),没必要对全字段建立索引,根据实际文本区分度决定索引长度就可 以。
- 尽量建立联合索引,而且在联合索引中将区分度高的字段放在前面,减少单列索引。(查询时,联合索引很多时候可以索引覆盖, 避免回表,提高效率)
- 在满足业务需求的前提下,建立适当的索引,索引不宜过多。(索引过多,会增加维护索引的成本,影响增删改的效率)
索引的使用
- 编写DQL时,在满足业务需要的情况下,要尽量避免索引失效的情况。
- 尽量使用索引覆盖,避免回表查询,提高性能。
- 那这些情况呢,都可以通过 explain 关键字来查看SQL语句的执行计划。
进阶优化手段(视业务规模而定)
- 那如果从数据库层面来讲,也可以基于读写分离的模式,来降低单台服务库的访问压力,从而提高效率。
- 当然,如果数据量过大,也可以考虑对目前项目中的数据库进行分库分表处理。