MySQL之性能优化步骤、索引(最左前缀原则、索引失效场景、索引设计原则)、SQL优化方案

193 阅读4分钟

性能优化步骤

  1. 首先我们通过查看数据库是什么以查询位置还是增删改为主,增删改的话就手动开启事务,并且批量提交数据。
  2. 如果是查询为主的话就开启慢查询日志
# 开启MySQL慢查询日志开关

slow_query_log=1

# 设置慢日志的时间为2秒,SQL语句执行时间超过2秒,就会视为慢查询,记录慢查询日志

long_query_time=2

慢查询日志会将超过设置时间的sql记录下来 3. 通过慢查询日志找到慢sql的id,用profiles查询每个阶段的耗时,可以有针对性的去优化 4. 之后通过explain执行计划看

  • type字段:是否走了索引,没走索引尽量走索引,从好到坏分别是const、eq_ref、ref、range、index、all,all的话是查全表,尽量不要。
  • possible_keys字段:指出MySQL能使用哪个索引在该表中找到行。如果是空的,没有相关的索引。这时要提高性能,可通过检验WHERE子句,看是否引用某些字段,或者检查字段是不是适合索引。
  • key_len字段:可以通过长度的变化看出用了联合索引的哪些字段
  • extra字段:会显示额外的信息,要注意的是排序:using index(索引排序)> Using filesort(缓冲区排序)

索引

最左前缀原则

简称最左原则,也就是想使用联合索引的时候,其最左边的那个字段必须存在,否则不能使用该联合索引。比如(name,age,class)做联合索引,where子句里必须有name,否则不能使用该联合索引,至于where子句里字段的顺序无所谓,where class ='class1' and age = 20 and name = 'Lin'也能使用该索引。

索引失效场景

部分失效

  • 当出现范围查询,用的是<、>的时候会出现右边索引失效,所以尽量使用<=、>=

完全失效

  • 不符合最左原则的
  • 字段使用函数或者进行运算的。这将会使优化器无法下手,导致索引失效
  • 字符串类型字段不加引号。相当于用函数隐式转换了,会失效。
  • 不等于。将全表检索
  • 用了or并且字段中有没有索引的
  • 用了like,%通配符在前面的,同时查询字段不覆盖索引的
  • 查询数据占所有数据的比重比较大的,mysql直接查全表

索引设计原则

  1. 在数据量大、经常查询的表上尽量建立索引
  2. 在经常select、group、order的字段建立索引
  3. 唯一索引要建立在区分度高的字段
  4. 尽量建立联合索引
  5. 对较长的字段建立前缀索引
  6. 控制索引数量
  7. 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含 NULL值时,它可以更好地确定哪个索引最有效地用于查询。

SQL优化方案

insert优化

小数据量

  1. 主键顺序插入
  2. 用values批量插入
  3. 手动开启事务,一次性提交

大数据量

用load命令插入数据

-- 客户端连接服务端时,加上参数 -–local-infile

mysql –-local-infile -u root -p

-- 设置全局参数local_infile为1,开启从本地加载文件导入数据的开关

set global local_infile = 1;

-- 执行load指令将准备好的数据,加载到表结构中

load data local infile '/root/sql1.log' into table tb_user fields

terminated by ',' lines terminated by '\n' ;

delete优化

跟insert一样,采用批量删除

update优化

where采用索引,这样就会用行锁否则会用表锁

主键优化

主键要选择顺序增长的,尽量短,插入数据也要尽量顺序插入

排序优化

  • 根据排序字段建立合适的索引,多字段排序时,也遵循最左前缀法则。
  • 尽量使用覆盖索引。
  • 多字段排序, 一个升序一个降序,此时需要注意联合索引在创建时的规则(ASC/DESC)。
  • 如果不可避免的出现filesort,大数据量排序时,可以适当增大排序缓冲区大小sort_buffer_size(默认256k)。

分组优化

  • 还是走索引

limit优化

子查询(多表关联) + 覆盖索引,也就是先查询到需要筛选数据的主键,然后再进行数据子查询或者表关联查询到需要的具体数据

count优化

尽量使用count(*)

  • count(*)不取值,按行累加
  • count(1)不取值,填入1按行累加
  • count(字段)取值,有时候需要判空(主键不需要判空,有约束不需要判空)

所以效率是count(*)=count(1)>count(字段)

参考