MySQL 性能优化 - 第一篇

查询各种 SQL 的执行频率

语法:show [session|global] status like ‘% Com_%’;
mysql-optimize-1

查询示例:

1
2
3
4
5
6
7
8
# 查询当前数据库执行CRUD操作的次数
show global status like 'com_select';
show global status like 'com_insert';
show global status like 'com_update';
show global status like 'com_delete';

# 查看当前数据库的连接数
show global status like 'connections';

慢查询优化

启用记录慢查询日志

注意:通过 MySQL 命令来修改慢查询相关参数,无论修改全局还是当前会话内的配置参数,在 MySQL 重启之后都会失效,想永久生效必须修改 MySQL 的配置文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 修改当前会话的慢查询定义时间
set long_query_time = 1;

# 或者修改全局默认的慢查询定义时间
set global long_query_time = 1;

# 查询是否开启了记录慢查询日志
show variables like '%slow%';

# 开启记录慢查询日志
set global slow_query_log = on;

# 查询慢查询发生的次数
show status like 'slow_queries';

# 查询默认的慢查询定义时间
show variables like 'long_query_time';

永久启用记录慢查询日志

MySQL5.6 开启慢查询日志,需要在配置文件 my.cnf 中添加以下配置。

1
2
3
4
5
6
7
8
# 慢查询时间
long_query_time=1

# 是否记录慢查询
slow_query_log=TRUE

# 慢查询日志文件的路径
slow_query_log_file=/var/log/mysqld-slow.log

索引优化

添加、删除索引

索引的类型包括主键索引、唯一索引、普通索引、全文索引,比较特殊的是复合索引 (单个索引作用在多列上),其中索引的添加、删除、使用率查询语法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 查询某张表的索引信息
show keys from table_xx;
show index from table_xx;

# 添加主键索引
alter table table_xx add primary key(column_name);

# 添加普通索引
create index index_name on table_xx(column_name);
alter table table_xx add index index_name(column_name);

# 添加唯一索引,唯一索引所在的列值可以为Null,同时可以存在多个Null
create unique index index_name on table_xx(column_name);
create table table_xx(id primary key auto_increment, name varchar(20) unique);

# 全文索引只对MyIsam存储引擎有效,且只针对英文生效;Mysql中可以使用sphinx(coreseek)技术处理中文的全文索引,正确使用全文索引查询的语法如下,其中title、body字段存在全文索引
select * from articles where match(title, body) against('tomcat');

# 删除索引(适用于唯一索引、普通索引、全文索引)
alter table table_xx drop index index_name;

# 删除主键索引
alter table table_xx drop primary key;

# 查看索引的使用率
show status like 'Handler_read%';

索引的适用场景

1
2
3
4
5
6
7
8
9
10
# 较频繁的作为查询条件字段应该创建索引
select * from emp where empno = 1

# 唯一性太差的字段不适合单独创建索引,即使是频繁作为查询条件
select * from emp where sex = '男'

# 更新非常频繁的字段不适合创建索引
select * from emp where logincount = 1

# 不会出现在WHERE子句中的字段不该创建索引

索引不生效的情况

  • 对于多列索引,如果不是使用的第一部分,则不会使用索引
  • 如果 MySQL 估算使用全表扫描要比使用索引快,则不会使用索引
  • like 查询,即是以 % 开头的查询不会使用索引,除非 select 数据列都加了索引
  • 如果列类型是字符串,那一定要在条件中将数据使用单引号包起来,否则索引不生效
  • 如果条件中有 or,即使其中有部分条件带索引也不会使用。换言之,必须所有列都建有索引才有效

锁优化

查询表级锁争用情况

mysql-optimize-2

其他优化

group by 优化

group by 之后默认会执行排序操作,可以使用 group by xxx order by null 强制不进行排序操作。