Modify by lyc at 2018-11-13:以下博文整理转自老叶茶馆博文。
参考博文:
老叶茶馆-比较全面的MySQL优化参考(上篇)
老叶茶馆-比较全面的MySQL优化参考(下篇)

一、服务器硬件层面(略)

服务器硬件层的优化(略),请参考老叶博客原文。

关闭 bios NUMA:NUMA(Non Uniform Memory Access Architecture),按我的理解就是让系统跨越CPU分配内存。

二、操作系统内核参数优化

1.锁住swap

散尽浮华-MySQL 针对Swap分区的运维注意点 (精华)

针对关键内核参数设定合适的值,目的是为了减少swap的倾向,并且让内存和磁盘I/O不会出现大幅波动,导致瞬间波峰负载

1
2
3
4
5
6
7
$ cat /proc/sys/vm/swappiness
60

$ vim /etc/sysctl.conf
vm.swappiness=1 # 锁住内存,减少swap交换

$ sysctl -p

2.系统脏页

文件系统缓存dirty_ratio与dirty_background_ratio两个参数区别

1
2
3
4
5
$ vim /etc/sysctl.conf
vm.dirty_background_ratio=5 # {5|10}
vm.dirty_ratio=10 # {10|20}设置为 vm.dirty_background_ratio 的两倍左右,以确保能持续将脏数据刷新到磁盘,避免瞬间I/O写,产生严重等待

$ sysctl -p
  • vm.dirty_background_ratio 这个参数指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如5%)就会触发pd flush/flush/kdmflush 等后台回写进程运行,将一定缓存的脏页异步地刷入外存。
  • vm.dirty_ratio 指定了当文件系统缓存脏页数量达到系统内存百分之多少时(如10%),系统不得不开始处理缓存脏页(因为此时脏页数量已经比较多,为了避免数据丢失需要将一定脏页刷入外存);在此过程中很多应用进程可能会因为系统转而处理文件IO而阻塞。

三、my.cnf 最重要的参数选项调整建议

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
default-storage-engine=InnoDB
强烈建议不要再使用MyISAM引擎了,InnoDB引擎绝对可以满足99%以上的业务场景

innodb_buffer_pool_size
如果是单实例且绝大多数是InnoDB引擎表的话,可考虑设置为物理内存的50% ~ 70%左右

innodb_flush_log_at_trx_commit=1
sync_binlog=1
如果要求数据不能丢失,那么两个都设为1。
如果允许丢失一点数据,高性能,则可分别设为2和10。
而如果完全不用care数据是否丢失的话(例如在slave上,反正大不了重做一次),则可都设为0。
这三种设置值导致数据库的性能受到影响程度分别是:高、中、低,也就是第一个会另数据库最慢,最后一个则相反;

innodb_file_per_table=1
使用独立表空间,我实在是想不出来用共享表空间有什么好处了

innodb_data_file_path = ibdata1:1G:autoextend
千万不要用默认的10M,否则在有高并发事务时,会受到不小的影响

innodb_log_file_size=256M
innodb_log_files_in_group=2
基本可满足90%以上的场景

long_query_time=1
在5.5版本以上,已经可以设置为小于1了
建议设置为0.05(50毫秒),记录那些执行较慢的SQL,用于后续的分析排查

max_connections=2048
根据实际业务,调整最大连接数

max_connect_errors=1000000
最大错误数,建议设置为10万以上

open_files_limit
innodb_open_files
table_open_cache
table_definition_cache
这几个参数则可设为约10倍于max_connection的大小


tmp_table_size
max_heap_table_size
常见的误区是把这两个设置的比较大,曾经见过设置为1G的,
这2个选项是每个连接会话都会分配的,因此不要设置过大,否则容易导致OOM发生

sort_buffer_size
join_buffer_size
read_buffer_size
read_rnd_buffer_size
其他的一些连接会话级选项例如:等,也需要注意不能设置过大


key_buffer_size=32M
由于已经建议不再使用MyISAM引擎了,因此可以把key_buffer_size设置为32M左右


query_cache_size=0
query_cache_type=0
最后强烈建议关闭query cache功能

四、关于Schema设计规范及SQL使用建议

  1. 所有的InnoDB表都设计一个无业务用途的自增列做主键,对于绝大多数场景都是如此,真正纯只读用InnoDB表的并不多,真如此的话还不如用TokuDB来得划算;
  2. 字段长度满足需求前提下,尽可能选择长度小的。此外,字段属性尽量都加上NOT NULL约束,可一定程度提高性能;
  3. 尽可能不使用TEXT/BLOB类型,确实需要的话,建议拆分到子表中,不要和主表放在一起,避免SELECT * 的时候读性能太差。
  4. 读取数据时,只选取所需要的列,不要每次都SELECT *,避免产生严重的随机读问题,尤其是读到一些TEXT/BLOB列;
  5. 对一个VARCHAR(N)列创建索引时,通常取其50%(甚至更小)左右长度创建前缀索引就足以满足80%以上的查询需求了,没必要创建整列的全长度索引;
  6. 通常情况下,子查询的性能比较差,建议改造成JOIN写法;
  7. 多表联接查询时,关联字段类型尽量一致,并且都要有索引;
  8. 多表连接查询时,把结果集小的表(注意,这里是指过滤后的结果集,不一定是全表数据量小的)作为驱动表;
  9. 多表联接并且有排序时,排序字段必须是驱动表里的,否则排序列无法用到索引;
  10. 多用复合索引,少用多个独立索引,尤其是一些基数(Cardinality)太小(比如说,该列的唯一值总数少于255)的列就不要创建独立索引了;
  11. 类似分页功能的SQL,建议先用主键关联,然后返回结果集,效率会高很多;

五、其他建议

  1. 通常地,单表物理大小不超过10GB,单表行数不超过1亿条,行平均长度不超过8KB,如果机器性能足够,这些数据量MySQL是完全能处理的过来的,不用担心性能问题,这么建议主要是考虑ONLINE DDL的代价较高;
  2. 不用太担心mysqld进程占用太多内存,只要不发生OOM kill和不用到大量的SWAP都还好
  3. 在以往,单机上跑多实例的目的是能最大化利用计算资源,如果单实例已经能耗尽大部分计算资源的话,就没必要再跑多实例了;
  4. 定期使用pt-duplicate-key-checker检查并删除重复的索引。定期使用pt-index-usage工具检查并删除使用频率很低的索引;
  5. 定期采集slow query log,用pt-query-digest工具进行分析,可结合Anemometer系统进行slow query管理以便分析slow query并进行后续优化工作;
  6. 可使用pt-kill杀掉超长时间的SQL请求,Percona版本中有个选项 innodb_kill_idle_transaction 也可实现该功能;
  7. 使用pt-online-schema-change来完成大表的ONLINE DDL需求;
  8. 定期使用pt-table-checksumpt-table-sync来检查并修复mysql主从复制的数据差异;