慢SQL
本篇文章总结自阿里技术篇
关于慢SQL
对于超过1s的SQL为慢SQL
慢SQL由于执行时间长,会导致:
- 系统的响应时间延迟,影响用户体验
- 资源占用增加,增高了系统的负载,其他请求响应时间也可能会收到影响。
- 慢SQL占用数据库连接的时间长,如果有大量慢SQL查询同时执行,可能会导致数据库连接池的连接被全部占用,导致数据连接池打满、缓冲区溢出等问题,使数据库无法响应其他请求。
- 还有可能造成锁竞争增加、数据不一致等问题
由此可见,需要及时发现和优化慢SQL,对保障系统稳定性是非常重要的。
产生的原因
产生慢SQL的原因可能有很多,以下是一些常见的原因:
- 缺乏索引/索引未生效,导致数据库全表扫描,会产生大量的IO消耗,产生慢SQL。
- 单表数据量太大,会导致加索引的效果不够明显。
- SQL语句书写不当,例如join或者子查询过多、in元素过多、limit深分页问题、order by导致文件排序、group by使用临时表等。
- 数据库在刷“脏页”,redo log写满了,导致所有系统更新被堵住,无法写入了。
- 执行SQL的时候,遇到表锁或者行锁,只能等待锁被释放,导致了慢SQL。
如何识别高危SQL
根据历史慢SQL治理经验,我们把高危SQL分为以下几类:
- 不符合集团SQL规约的SQL,可能会埋坑,造成线上问题,影响执行效率等。
- 通过对SQL语句分析,发现SQL索引使用不当、造成全表扫描,或者SQL扫描行数过多、出现文件排序等。这种SQL即使当前不是慢SQL,随着表数据量的膨胀,未来也可能发展为慢SQL。
- SQL执行时间过长,比较容易理解。对慢SQL来说,执行时间越长,风险越高。
SQL规约
集团重点强制SQL规约如下:
- 【强制】不要使用count(列名)或count(常量)来替代count(*),count(*)就是SQL92定义的标准统计行数的语法,跟数据库无关,跟NULL和非NULL无关。
- 【强制】count(distinct col) 计算该列除NULL之外的不重复数量。注意 count(distinct col1, col2) 如果其中一列全为NULL,那么即使另一列有不同的值,也返回为0。
- 【强制】当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为NULL,因此使用sum()时需注意NPE问题。
- 【强制】使用ISNULL()来判断是否为NULL值。
- 【强制】对于数据库中表记录的查询和变更,只要涉及多个表,都需要在列名前加表的别名(或表名)进行限定。
- 【强制】在代码中写分页查询逻辑时,若count为0应直接返回,避免执行后面的分页语句。
- 【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
- 【强制】禁止使用存储过程,存储过程难以调试和扩展,更没有移植性。
- 【强制】IDB数据订正(特别是删除或修改记录操作)时,要先select,避免出现误删除,确认无误才能提交执行。
SQL索引
SQL explain语句可以提供关于SQL查询执行的详细信息和执行计划,并且可以了解sql的索引使用情况以及数据访问方式。通过使用Explain语句,可以了解SQL是如何执行的,并且可以看出其可能存在的性能问题。
我们重点关注的点如下:
- 使用全表扫描,性能最差,即type="ALL"
- 扫描行数过多,即rows>阈值
- 查询时使用了排序操作,也比较耗时,即Extra包含"Using filesort"
- 索引类型为index,代表全盘扫描了索引的数据,Extra信息为Using where,代表要搜索的列没有被索引覆盖,需要回表,性能较差。
评论区