it编程 > 数据库 > MsSqlserver

慢SQL是什么原因导致的?如何定位和优化慢查询

58人参与 2026-08-20 MsSqlserver

慢sql

指执行时间超过预定阈值的sql,通常由long_query_time参数设定,默认为10秒。

定位

[mysqld] 
slow_query_log=1 //开启慢查询日志
slow_query_log_file=/var/lib/mysql/mysql-slow.log 	//慢查询日志存放路径   
long_query_time=3 //慢查询阈值
log_output=file
 

通过在mysql客户端执行命令开启(重启后失效) 如下:

set global slow_query_log = ‘on';
set global slow_query_log_file = ‘/var/lib/mysql/mysql-slow.log';
set global long_query_time = 3;

分析

通过执行 在对应sql前 添加 explain后的sql 得到该sql的执行计划 如下

    id  select_type  table    partitions  type    possible_keys  key       key_len  ref       rows  filtered  extra        
------  -----------  -------  ----------  ------  -------------  --------  -------  ------  ------  --------  -------------
     1  simple       student  (null)      index   (null)         name_age  68       (null)      10    100.00  using index  

主要关注 type、key、rows、extra

type

代表此次执行该sql所使用的索引类型

索引类型的效率:

null > system > const > eq_ref > ref > ref_or_null > index_merge > range > index > all

range 指使用索引列进行范围条件查询如

=, <>, >, >=, <, <=, is null, <=>, between, in

key

实际上使用的索引名称(建立索引时定义),没有用索引则为null

rows

指mysql估计该sql通过索引(走了索引时)所要读取到server层的数据行数,同一sql在不同索引下,数值越小代表索引越好

filtered

估计读取到server层后没有被过滤掉的数据行数比例 n/rows*100%

extra

mysql的索引优化信息

索引优化

最左前缀匹配

联合索引建立时的索引顺序通过使用频率,字段区分度及范围查询(导致后面索引失效)来进行建立

如 sql:

select * from student where score=60 and finished_time >'2000-10-10'

建立索引

idx_score_finished(score,finished)

注:具体需根据业务场景进行判断

索引覆盖

在高频、少字段的sql中,考虑对字段加联合索引,实现索引覆盖

如 sql:

select name,score from student where finished_time ='2000-10-10'

建立索引

idx_finished_name_score

索引下推

对查询条件建立索引,减少回表到server层进行过滤的行数(当查询条件中存在不生效索引或不存在索引时,需要将数据传到server层进行过滤)

如 sql:

select score from student where name ='stu' and finished_time ='2000-10-10'

建立索引

idx_name_finished

表结构优化

数据类型

如果确定该列不为null(有默认值),勾选not null省去部分空间

数字类型

字符类型

日期类型

字符编码

如果对字符要求不高,可以不选utf等有冗余的编码方式,按需选字符集

注:有联表关系的表的表间关联键的字符集应保持一致,避免关联时字符集不同导致索引失效

​​范式与反范式平衡

可以根据业务需求进行反范式设计,即添加冗余字段

如: product表 kind表 可在product表上冗余kind_name字段

大字段如text会影响数据行加载到内存页的速度(大字段会行溢出,引入磁盘io),可以拆分为表,使用关联方式读取

sql优化

  1. 按需select, 避免使用select*,减少网络io带宽消耗
  2. 索引字段避免使用mysql的隐式转换,如bigint的id传int64,而不是字符串,避免索引失效
  3. like避免将通配符加到左侧,避免不遵守最左前缀原则导致索引失效
  4. 避免在索引列上使用mysql内置函数(server层),导致索引失效
  5. 避免对索引列进行运算
  6. 对索引列等值查询时,使用= 而不是<>
  7. 多表操作如join,in时使用小表驱动大表的sql编写,减少关联数据量
  8. 批量操作在业务层进行分批,sql中进行批量执行,避免并发数据插入带来的锁竞争
  9. 使用limit减少每次回传的数据行数以及数据库回表行数,减少网络io及sql执行时间
  10. 深分页使用延时分页优化:将符合条件的id limit查出来后再去主表联表,省去二次回表

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

您想发表意见!!点此发布评论

推荐阅读

SQL Server数据库完整备份、差异备份与日志备份的实操指南

08-19

SQL Server中临时表与表变量的实战场景对比

08-19

Oracle SQL检索数据实用技巧与实战案例

08-19

PostgreSQL PgAdmin与DBeaver图形化管理工具详解

08-19

SQL数据库性能故障排查与索引设计实战指南

08-18

Oracle之SQL的子查询使用及说明

08-23

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论