MySQL优化---DBA对MySQL优化的一些总结

2018-01-16 23:53:52  阅读 686 次 评论 0 条

本文整理了一些MySQL的通用优化方法,做个简单的总结分享,旨在帮助那些没有专职MySQL DBA的企业做好基本的优化工作,至于具体的SQL优化,大部分通过加适当的索引即可达到效果,更复杂的就需要具体分析了,可以参考本站的一些优化案例或者联系我,下方有我的联系方式。这是上篇。

1、硬件层相关优化

1.1、CPU相关

在服务器的BIOS设置中,可调整下面的几个配置,目的是发挥CPU最大性能,或者避免经典的NUMA问题:

1、选择Performance Per Watt Optimized(DAPC)模式,发挥CPU最大性能,跑DB这种通常需要高运算量的服务就不要考虑节电了;
2、关闭C1E和C States等选项,目的也是为了提升CPU效率;
3、Memory Frequency(内存频率)选择Maximum Performance(最佳性能);

4、内存设置菜单中,启用Node Interleaving,避免NUMA问题;

1.2、磁盘I/O相关

下面几个是按照IOPS性能提升的幅度排序,对于磁盘I/O可优化的一些措施:

1、使用SSD或者PCIe SSD设备,至少获得数百倍甚至万倍的IOPS提升;
2、购置阵列卡同时配备CACHE及BBU模块,可明显提升IOPS(主要是指机械盘,SSD或PCIe SSD除外。同时需要定期检查CACHE及BBU模块的健康状况,确保意外时不至于丢失数据);

3、有阵列卡时,设置阵列写策略为WB,甚至FORCE WB(若有双电保护,或对数据安全性要求不是特别高的话),严禁使用WT策略。并且闭阵列预读策略,基本上是鸡肋,用处不大;

4、尽可能选用RAID-10,而非RAID-5;

5、使用机械盘的话,尽可能选择高转速的,例如选用15KRPM,而不是7.2KRPM的盘,不差几个钱的;

2、系统层相关优化

2.1、文件系统层优化

在文件系统层,下面几个措施可明显提升IOPS性能:

1、使用deadline/noop这两种I/O调度器,千万别用cfq(它不适合跑DB类服务);
2、使用xfs文件系统,千万别用ext3;ext4勉强可用,但业务量很大的话,则一定要用xfs;

3、文件系统mount参数中增加:noatime, nodiratime, nobarrier几个选项(nobarrier是xfs文件系统特有的);

2.2、其他内核参数优化

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

1、将vm.swappiness设置为5-10左右即可,甚至设置为0(RHEL 7以上则慎重设置为0,除非你允许OOM kill发生),以降低使用SWAP的机会;
2、将vm.dirty_background_ratio设置为5-10,将vm.dirty_ratio设置为它的两倍左右,以确保能持续将脏数据刷新到磁盘,避免瞬间I/O写,产生严重等待(和MySQL中的innodb_max_dirty_pages_pct类似);

3、将net.ipv4.tcp_tw_recycle、net.ipv4.tcp_tw_reuse都设置为1,减少TIME_WAIT,提高TCP效率;

4、至于网传的read_ahead_kb、nr_requests这两个参数,我经过测试后,发现对读写混合为主的OLTP环境影响并不大(应该是对读敏感的场景更有效果),不过没准是我测试方法有问题,可自行斟酌是否调整;

本文整理了一些MySQL的通用优化方法,做个简单的总结分享,旨在帮助那些没有专职MySQL DBA的企业做好基本的优化工作,至于具体的SQL优化,大部分通过加适当的索引即可达到效果,更复杂的就需要具体分析了,可以参考本站的一些优化案例或者联系我,下方有我的联系方式。这是下篇。

3、MySQL层相关优化

3.1、关于版本选择

官方版本我们称为ORACLE MySQL,这个没什么好说的,相信绝大多数人会选择它。

我个人强烈建议选择Percona分支版本,它是一个相对比较成熟的、优秀的MySQL分支版本,在性能提升、可靠性、管理型方面做了不少改善。它和官方ORACLE MySQL版本基本完全兼容,并且性能大约有20%以上的提升,因此我优先推荐它,我自己也从2008年一直以它为主。

另一个重要的分支版本是MariaDB,说MariaDB是分支版本其实已经不太合适了,因为它的目标是取代ORACLE MySQL。它主要在原来的MySQL Server层做了大量的源码级改进,也是一个非常可靠的、优秀的分支版本。但也由此产生了以GTID为代表的和官方版本无法兼容的新特性(MySQL 5.7开始,也支持GTID模式在线动态开启或关闭了),也考虑到绝大多数人还是会跟着官方版本走,因此没优先推荐MariaDB。

3.2、关于最重要的参数选项调整建议

建议调整下面几个关键参数以获得较好的性能(可使用本站提供的my.cnf生成器生成配置文件模板):

1、选择Percona或MariaDB版本的话,强烈建议启用thread pool特性,可使得在高并发的情况下,性能不会发生大幅下降。此外,还有extra_port功能,非常实用, 关键时刻能救命的。还有另外一个重要特色是 QUERY_RESPONSE_TIME 功能,也能使我们对整体的SQL响应时间分布有直观感受;

2、设置default-storage-engine=InnoDB,也就是默认采用InnoDB引擎,强烈建议不要再使用MyISAM引擎了,InnoDB引擎绝对可以满足99%以上的业务场景;

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

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

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

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

7、设置innodb_log_file_size=256M,设置innodb_log_files_in_group=2,基本可满足90%以上的场景;

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

9、根据业务实际需要,适当调整max_connection(最大连接数)、max_connection_error(最大错误数,建议设置为10万以上,而open_files_limit、innodb_open_files、table_open_cache、table_definition_cache这几个参数则可设为约10倍于max_connection的大小;

10、常见的误区是把tmp_table_size和max_heap_table_size设置的比较大,曾经见过设置为1G的,这2个选项是每个连接会话都会分配的,因此不要设置过大,否则容易导致OOM发生;其他的一些连接会话级选项例如:sort_buffer_size、join_buffer_size、read_buffer_size、read_rnd_buffer_size等,也需要注意不能设置过大;

11、由于已经建议不再使用MyISAM引擎了,因此可以把key_buffer_size设置为32M左右,并且强烈建议关闭query cache功能;

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

下面列举了几个常见有助于提升MySQL效率的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,建议先用主键关联,然后返回结果集,效率会高很多;

3.3、其他建议

关于MySQL的管理维护的其他建议有:

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-checksum、pt-table-sync来检查并修复mysql主从复制的数据差异;
分类: mysql优化

1. 要确保有足够的内存
数据库能够高效的运行,最关建的因素需要内存足更大了,能缓存住数据,更新也可以在内存先完成。但不同的业务对内存需要强度不一样,一推荐内存要占到数据的15-25%的比例,特别的热的数据,内存基本要达到数据库的80%大小。

2. 需要更多更快的CPU
MySQL 5.6可以利用到64个核,而MySQL每个query只能运行在一个CPU上,所以要求更多的CPU,更快的CPU会更有利于并发。

3. 要选择合适的操作系统
在官方建议估计最推荐的是Solaris, 从实际生产中看CentOS, REHL都是不错的选择,推荐使用CentOS, REHL 版本为6以后的,当然Oracle Linux也是一个不错的选择。虽然从MySQL 5.5后对Windows做了优化,但也不推荐在高并发环境中使用windows.

4. 合理的优化系统的参数
更改文件句柄  ulimit –n 默认1024 太小
进程数限制  ulimit –u   不同版本不一样
禁掉NUMA  numctl –interleave=all

5. 选择合适的内存分配算法
默认的内存分配就是c的malloc 现在也出现许多优化的内存分配算法:
jemalloc and tcmalloc
从MySQL 5.5后支持声明内存储方法。
[mysqld_safe]
malloc-lib = tcmalloc
 
或是直接指到so文件
[mysqld_safe]
malloc-lib=/usr/local/lib/libtcmalloc_minimal.so

6. 使用更快的存储设备ssd或是固态卡
存储介质十分影响MySQL的随机读取,写入更新速度。新一代存储设备固态ssd及固态卡的出现也让MySQL 大放异彩,也是淘宝在去IOE中干出了一个漂亮仗。

7. 选择良好的文件系统
推荐XFS, Ext4,如果还在使用ext2,ext3的同学请尽快升级别。 推荐XFS,这个也是今后一段时间Linux会支持一个文件系统。
文件系统强烈推荐: XFS

8. 优化挂载文件系统的参数
挂载XFS参数:
(rw, noatime,nodiratime,nobarrier)
挂载ext4参数:
ext4 (rw,noatime,nodiratime,nobarrier,data=ordered)
如果使用SSD或是固态盘需要考虑:
? innodb_page_size = 4K
? Innodb_flush_neighbors = 0

9. 选择适合的IO调度
正常请下请使用deadline 默认是noop
echo dealine >/sys/block/{DEV-NAME}/queue/scheduler

10. 选择合适的Raid卡Cache策略
请使用带电的Raid,启用WriteBack, 对于加速redo log ,binary log, data file都有好处。

11. 禁用Query Cache
QueryCache在Innodb中有点鸡肋,Innodb的数据本身可以在Innodb buffer pool中缓存,Query Cache属于结果集缓存,如果开启Query Cache更新写入都要去检查query cache反而增加了写入的开销。
在MySQL5.6中Querycache是被禁掉了。

12. 使用Thread Pool
现在一个数据对应5个以上App场景比较,但MySQL有个特性随着连接增多的情况下性能反而下降,所以对于连接超过200的以后场景请考虑使用thread pool. 这是一个伟大的发明。

13. 合理调整内存
13.1 减少连接的内存分配
连接可以用thread_cache_size缓存,观查属于比较属不如thread pool给力。数据库在连上分配的内存如下:
max_used_connections * (
read_buffer_size +
read_rnd_buffer_size +
join_buffer_size +
sort_buffer_size +
binlog_cache_size +
thread_stack +
2 * net_buffer_length …
)
13.2 使较大的buffer pool
要把60-80%的内存分给innodb_buffer_pool_size.  这个不要超过数据大小了,另外也不要分配超过80%不然会利用到swap.


14. 合理选择LOG刷新机制
Redo Logs:
– innodb_flush_log_at_trx_commit  = 1 // 最安全
– innodb_flush_log_at_trx_commit  = 2 //  较好性能
– innodb_flush_log_at_trx_commit  = 0 //  最好的情能
binlog :
binlog_sync = 1  需要group commit支持,如果没这个功能可以考虑binlog_sync=0来获得较佳性能。
数据文件:
innodb_flush_method = O_DIRECT

15. 请使用Innodb表
可以利用更多资源,在线alter操作有所提高。 目前也支持非中文的full text, 同时支持Memcache API访问。目前也是MySQL最优秀的一个引擎。
如果你还在MyISAM请考虑快速转换。

16. 设置较大的Redo log
以前Percona 5.5和官方MySQL 5.5比拼性能时,胜出的一个Tips就是分配了超过4G的Redo log ,而官方MySQL5.5 redo log不能超过4G. 从 MySQL 5.6后可以超过4G了,通常建Redo log加起来要超过500M。 可以通过观查redo log产生量,分配Redo log大于一小时的量即可。

17. 优化磁盘的IO
innodb_io_capactiy 在sas 15000转的下配置800就可以了,在ssd下面配置2000以上。
在MySQL 5.6:
innodb_lru_scan_depth =  innodb_io_capacity / innodb_buffer_pool_instances
innodb_io_capacity_max  =  min(2000, 2 * innodb_io_capacity)

18. 使用独立表空间
目前来看新的特性都是独立表空间支持:
truncate table 表空间回收
表空间传输
较好的去优化碎片等管理性能的增加,
整体上来看使用独立表空间是没用的。

19. 配置合理的并发
innodb_thread_concurrency =并发这个参数在Innodb中变化也是最频繁的一个参数。不同的版本,有可能不同的小版本也有变动。一般推荐:
在使用thread pool 的情况下:
innodb_thread_concurrency = 0 就可以了。
如果在没有thread pool的情况下:
5.5 推荐:innodb_thread_concurrency =16 – 32
5.6 推荐innodb_thread_concurrency = 36

20. 优化事务隔离级别
默认是 Repeatable read
推荐使用Read committed  binlog格式使用mixed或是Row
较低的隔离级别 = 较好的性能

21. 注重监控
任环境离不开监控,如果少了监控,有可能就会陷入盲人摸象。 推荐zabbix+mpm构建监控

本文转载

本文地址:http://blog.ailinux.net/post/38.html
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

发表评论


表情

还没有留言,还不快点抢沙发?