使用须知
- 不要错误得把它当做一个文件存储,如图片、附件等放入MySQL中,容易导致表空间庞大,磁盘I/O的读写能性能很差
- 不要把MySQL数据库当成一个计算器,在其中进行大量复杂的运算
- 不要把它当成一个全文检索工具,单纯地把MySQL当成一个可以处理并发事务,保证数据一致性的数据库就可以了
特点
从CPU、内存、磁盘三个方面阐述
1、CPU
MySQL5.1版本之前的多核支持能力很差,随着后期版本的升级,用到的CPU核数越来越多,5.6版本已经可以用到64核,建议定期升级MySQL线上的版本到最新的稳定版本
当每个连接进入数据库是,MySQL都会创建一个线程来响应此连接的请求。每个SQL语句只能用一个CPU核心,如果此SQL语句执行很缓慢,就容易出现锁等待、排队等现象。所以设计的业务逻辑不要过于复杂,避免写那种很多表的连接的SQL语句,尽量让SQL语句快速执行成功,在项目初期设计表时,数据类型越简单越好
2、内存
MySQL内存组成和Oracle类似,可以分为SGA(系统全局区)和PGA(程序缓存区)。每个连接会话连到数据库时,都会为其分配内存,分配的内存大小一定控制好,不宜过大,防止当业务高峰,连接数过高时,有可能出现OOM现象(内存溢出)。
相比Oracle的内存管理机制,MySQL的内存管理还是很简单。在InnoDB存储引擎中实现了自己的内存池系统和内存堆分配系统,在InnoDB的内存管理系统中,大致分为基础的内存块分配管理、内存伙伴分配器和内存堆分配器三个部分。InnoDB定义和实现内存池的主要目的是提供内存的使用率和效率,防止内存碎片和内存分配跟踪和调试。内存的主要作用就是缓存热点数据,尽量保证所有的读取操作都在内存中完成,避免产生过多的物理I/O。
在业务高峰期,高并发的环境下,我们可以适当增加物理内存大小,来提高数据库的并发性能。
innodb_buffer_pool
作用是缓存InnoDB表的数据、索引、插入缓冲、数据字典等信息。如果是单实例,且数据库中绝大部分是InnoDB存储引擎表,它的大小可以考虑设置为物理内存的50%-80%。
query cache
建议关闭,可以选择Redis、Memcache或MangoDB来缓存热点数据层
3、磁盘
MySQL的binlog文件、存储引擎文件undo和redo都是顺序写入的方式,数据文件是伴随顺序写和随机写一起。
OLTP这类业务系统都是以随机I/O为主,可以通过增加内存来提升数据库读写性能
4个维度优化
优化SQL,需要从4个维度方面优化,从下到上为 硬件设备优化、MySQL数据库、Linux操作系统、表设计
硬件优化
影响数据库最大的性能问题就是磁盘I/O,为了提升数据库IOPS性能,可以使用SSD或PCIE-SSD高速磁盘设备,至少可以获得上百倍或者上万倍的IOPS系能提升
当数据库系统TPS过高或者业务量叫较高时,一定要配置阵列卡(RAID 1+ 0
),而且阵列卡一直要配备cache模块,cache模块还要配置BBU模块来提供持续的电量。在选择阵列卡的cache策略是,为了提高I/O写数据性能,建议设置为Write Back(WB)
,这种策略是将数据先写到cache中,然后通过阵列卡控制刷回到磁盘里面
在服务器BIOS层面也可以对MySQL数据库的优化进行一些配置参数的设置。CPU建议采用最大性能模式,选择performance per watt optimized
来充分发挥CPU的最大功耗性能,同时建议关闭C1E
和C stats
这类节能选项,因为当负载增加,或者访问量变大时,有可能造成数据库响应不了太大的请求,从而出现数据库性能变慢、卡住的现象,甚至可能MySQL服务宕机
内存方面也要选择最大系能模式maximum performance
,尽量在BIOS里面禁掉NUMA功能,将Node Interleaving设置为Enabled模式,让内存在多个CPU节点之间进行循环使用,这样可以更好地利用内存
配置参数优化
innodb_buffer_pool
如果是单实例且绝大数是InnoDB引擎表,则可以设置为物理内存50%~80%左右innodb_flush_log_at_trx_commit
和sync_binlog
分别是redo log刷新和bin log 刷新的参数。如果要求数据不能丢失,建议把这两个参数都设置为1,可以保证主从架构中数据的一致性。想保证其强一致性,可以考虑增强半同步功能innodb_max_dirty_pages_pct
指脏页占innodb buffer pool的比例。 当比例到达所设置的值,触发脏页刷盘,建议25%-50%innodb_io_capacity
InnoDB后台进程最大的I/O性能指标,影响刷新脏页和插入缓冲的数量。默认设置200,在高转速磁盘下,可以适当提高,SSD建议 5000-2000,PCIE-SSD 建议 50000左右innodb_data_file_path = ibdata1:1G:autoextend
long_query_time
记录慢查询sql时间,建议0.1~0.5,后续优化sqlbinlog_format
binlog 的记录格式 建议 row格式interactive_timeout,wait_timeout
分别代表交互等待时间和非交互等待时间 建议 300~500smax_connections
最大连接数 超过 容易产生OOM,kill
掉MySQL服务innodb_log_file_size
redo log的值 , 值太大,当实例恢复时,会消耗大量时间,值太小会造成日志切换频繁gerenal log
全量日志建议关闭 ,否则该日志文件会越来越大,造成磁盘空间的紧张,MySQL性能下降
linux层面对MySQL优化
- IO调度建议选 deadline或noop模式,不要选cfg模式
cat /sys/block/sda/queue/scheduler
-
文件系统 建议选择xfs,其次ext4
-
内核参数
vm.swapiness
使用swap的意向,可以在1~10范围内取值查看
cat /proc/sys/vm/swappiness
在/etc/sysctl.conf
vm.swappiness=0 禁用swap,可能出现OOM现象
vm.swappiness=1 尽量不使用swap
vm.swappiness=60 默认值
vm.swappiness=100 积极得使用swap,很影响性能
vm.dirty_background_ratio
当文件系统缓存脏页数量到达系统内存的百分比多少时,就会触发pdflush/flush/kdmflush
等后台回写进程运行,将一定的缓存的脏页异步刷入磁盘,建议不超过10vm.dirt_ratio
指定了当文件系统脏页数量达到系统内存百分比多少时,系统不得不开始处理缓存脏页
表设计及其他优化
- (1) 在创建业务表时,库名、表名、字段名必须使用小写字母,采用
_
分割 - (2) MySQL数据库中,通过
lower_case_table_name
区分表的大小写,默认为0,代表大小写敏感,如果是1,代码大小写不敏感,以小写存储。为字段选取数据类型时,秉承简单、够用的原则。表中的字段和索引数量不宜过多,要保证SQL语句查询的高效性,快速执行完,避免出现阻塞、排队现象 - (3) 表的存储引擎选择InnoDB
- (4) 要显式地为表创建一个使用自增列INT或BIGINT类型的主键,可以保证写入顺序是自增的,和B+tree叶子节点分裂顺序一直。写入更加高效,TPS性能会更高,存储效率也是最高的
- (5) 金钱、日期时间、IPv4尽量使用int存储
- (6) text和blob这种存大量文字或者图片的大数据类型,建议不要与业务表放在一起
- (7) 用select查询表示只需要获取必要的字段,避免使用 select * 。 可以减少网络带宽的消耗,还有可能利用到覆盖索引
- (8) 很长的字符串可以创建前缀索引