MySQL 性能调优(2)

MySQL数据库技术的方方面面也是不少,这里只涉及必备的性能调优,推崇从下向上的性能调优,主要包括运行环境,配置参数,SQL性能,和系统架构设计调优。mysql

运行环境调优linux

这里是Linux的天下,MySQL 运行环境的调优每每和Linux的内核调优一并完成。固然了,对云服务RDS 也有必定的参考做用。redis

调整Linux默认的IO调度算法算法

IO调度器的整体目标是但愿让磁头可以老是往一个方向移动,移动到底了再往反方向走,这偏偏就是现实生活中的电梯模型,因此IO调度器也被叫作电梯 (elevator),而相应的算法也就被叫作电梯算法.而Linux中IO调度的电梯算法有好几种,一个叫作as(Anticipatory),一个叫作 cfq(Complete Fairness Queueing),一个叫作deadline,还有一个叫作noop(No Operation).sql

IO对数据库的影响较大,linux默认的IO调度算法为cfq,须要修改成deadline,若是是SSD或者PCIe-SSD设备,须要修改成noop,可使用下面两种修改方式。数据库

一、在线动态修改,重启失效。缓存

echo “deadline” > /sys/block/sda/queue/scheduler安全

二、修改/etc/grub.conf,永久生效。服务器

修改/etc/grub.conf配置文件,在kernel那行增长一个配置,例如:session

elevator=deadline

主要关注elevator这个参数,设置内核的话须要重启系统才能生效。

禁用numa特性

新一代架构的NUMA不适合跑数据库,NUMA是为了内存利用率的提升,但反而可能致使一CPU的内存尚有剩余,另一个却不够用了,发生swap的问题,所以通常建议关闭或修改NUMA的调度。

一、修改/etc/grub.conf关闭NUMA,重启后生效。

numa=off

二、修改/etc/init.d/mysql或mysqld_safe脚本,设置启动mysqld进程时的NUMA调度机制,如 numactl –interleave=all。

修改swappiness设置

swappiness是linux的一个内核参数,用来控制物理内存交换出去的策略.它容许一个百分比的值,最小的为0,最大的为100,改值默认是60.这个设置值到底有什么影响呢?

vm.swappiness设置为0表示尽可能少使用swap,100表示尽可能将inactive的内存页交换到swap里或者释放cache。inactive内存的意思是程序映射着,可是”长时间”不用的内存。咱们能够利用vmstat查看系统里面有多少inactive的内存。

# vmstat -a 1

这个值推荐设置为1,设置方法以下,在/etc/sysctl.conf文件中增长一行。

vm.swappiness = 1

扩大文件描述符

这个是常常修改的参数,高并发的程序都会修改.

一、动态修改,重启失效,只能使用root,而且当前session有效。

ulimit -n 51200

二、修改配置文件,永久生效。

在/etc/security/limits.conf配置文件中增长

* hard nofile 51200

 

* soft nofile 51200

面向session的进程文件描述符的修改稍有不一样,在云上的修改也略有差别,能够参见同样的“open too many files”

优化文件系统挂载参数

对于文件系统,如无特殊要求,最好采用ext4.

文件系统挂载参数是在/etc/fstab文件中修改,重启时候生效。
noatime表示不记录访问时间,nodiratime不记录目录的访问时间。
barrier=0,表示关闭barrier功能.

barrier的主要目的是为了保证磁盘写数据的安全性,可是会下降性能。若是有BBU之类的电池备份电源保证控制卡不瞬间掉电,那么这个功能就能够放心大胆的关闭。

 

配置参数调优

 

my.cnf中的配置参数调优取决于业务,负载或硬件,在慢内存和快磁盘、高并发和写密集型负载状况下,都须要特殊的调整。

基本配置

query_cache_size
query cache是一个众所周知的瓶颈,甚至在并发并很少时也如此。 最 好是一开始就停用,设置query_cache_size = 0,并利用其余方法加速查询:优化索引、增长拷贝分散负载或者启用额外的缓存(好比memcache或redis)。若是已经启用了query cache而且尚未发现任何问题,query cache可能有用。若是想停用它,那就得当心了。

innodb_buffer_pool_size

缓冲池是数据和索引缓存的地方:这个值越大越好,这能保证你在大多数的读取操做时使用的是内存而不是硬盘。典型的值是5-6GB(8GB内存),20-25GB(32GB内存),100-120GB(128GB内存)。

innodb_log_file_size

redo日志被用于确保写操做快速而可靠而且在崩溃时恢复。从MySQL 5.5以后,崩溃恢复的性能的到了很大提高,能够同时拥有较高的写入性能和崩溃恢复性能。在MySQL 5.6里能够被提升到4GB以上。若是应用程序须要频繁的写入数据,能够一开始就把它这是成4G。

max_connections
max_connection值被设高了(例如1000或更高)以后一个主要缺陷是当服务器运行1000个或更高的活动事务时会变的没有响应。在应用程序里使用链接池或者在MySQL里使用进程池有助于解决这一问题。

back_log
要求 mysql 能有的链接数量。当主要mysql线程在一个很短期内获得很是多的链接请求,这就起做用,而后主线程花些时间检查链接而且启动一个新线程。back_log指明在mysql暂时中止回答新请求以前的短期内多少个请求能够被存在堆栈中。只有若是指望在一个短期内有不少链接,须要增长它,换句话说,该值对到来的tcp/ip链接的侦听队列的大小。

Innodb配置

innodb_file_per_table

这项设置告知InnoDB是否须要将全部表的数据和索引存放在共享表空间里(innodb_file_per_table = OFF)或者为每张表的数据单独放在一个.ibd文件(innodb_file_per_table = ON)。每张表一个文件容许你在drop、truncate或者rebuild表时回收磁盘空间。这对于一些高级特性也是有必要的,好比数据压缩。可是它不会带来任何性能收益。MySQL 5.6中,这个属性默认值是ON。

innodb_flush_log_at_trx_commit

默认值为1,表示InnoDB彻底支持ACID特性。当关注点是数据安全的时候这个值是最合适的,好比在一个主节点上。可是对于磁盘(读写)速度较慢的系统,它会带来很巨大的开销,由于每次将改变flush到redo日志都须要额外的fsyncs。若是值为0速度就更快了,但在系统崩溃时可能丢失一些数据, 因此一遍只适用于备份节点。

 

innodb_flush_method

 

这项配置决定了数据和日志写入硬盘的方式。通常来讲,若是你有硬件RAID控制器,而且其独立缓存采用write-back机制,并有着电池断电保护,那么应该设置配置为O_DIRECT;不然,大多数状况下应将其设为fdatasync(默认值)。sysbench是一个能够帮助你决定这个选项的好工具。

 

innodb_log_buffer_size

 

这项配置决定了为还没有执行的事务分配的缓存。可是若是事务中包含有二进制大对象或者大文本字段的话,看Innodb_log_waits状态变量,若是它不是0,增长innodb_log_buffer_size。

 

其余配置

 

log_bin

 

若是数据库服务器充当主节点的备份节点,那么开启二进制日志是必须的。就算只有一个服务器,若是你想作基于时间点的数据恢复,这也是颇有用的。二进制日志一旦建立就将永久保存。若是不想让磁盘空间耗尽,你能够用 PURGE BINARY LOGS 来清除旧文件,或者设置 expire_logs_days 来指定过多少天日志将被自动清除。记录二进制日志不是没有开销的,因此若是你在一个非主节点的复制节点上不须要它的话,那么建议关闭这个选项。

 

interactive_timeout

 

服务器在关闭它前在一个交互链接上等待行动的秒数。一个交互的客户被定义为对 mysql_real_connect()使用 client_interactive 选项的客户。 默认数值是28800,建议改成7200。

 

table_open_cache

 

MySQL每打开一个表,都会读入一些数据到table_open_cache缓存中,当MySQL在这个缓存中找不到相应信息时,才会去磁盘上读取。假定系统有200个并发链接,则需将此参数设置为200*N(N为每一个链接所需的文件描述符数目);当把table_open_cache设置为很大时,若是系统处理不了那么多文件描述符,那么就会出现客户端失效,链接不上。

 

max_allowed_packet

 

接受的数据包大小;增长该变量的值十分安全,这是由于仅当须要时才会分配额外内存。例如,仅当你发出长查询或MySQLd必须返回大的结果行时MySQLd才会分配更多内存。该变量之因此取较小默认值是一种预防措施,以捕获客户端和服务器之间的错误信息包,并确保不会因偶然使用大的信息包而致使内存溢出

 

skip_name_resolve

 

当客户端链接数据库服务器时,且当DNS很慢时,创建链接也会很慢。所以建议在启动服务器时关闭skip_name_resolve选项而不进行DNS查找。

 

SQL 语句调优

 

在应用层,经过pt工具和慢查询日志的配合,能够轻松地分辨出全表扫描的语句。

 

基本原则

 

  • 避免全表扫描

     

  • 创建索引

     

  • 尽可能避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理

     

  • 尽可能避免大事务操做,提升系统并发能力

     

  • 使用基于游标的方法或临时表方法以前,应先寻找基于集的解决方案来解决问题,基于集的方法一般更有效。尽可能避免使用游标,由于游标的效率较差。

 

雕虫小技

 

关于where 后的条件

 

  • 应尽可能避免在 where 子句中使用 != 或 <> 操做符,不然将引擎放弃使用索引而进行全表扫描。

     

  • 应尽可能避免在 where 子句中使用 or 来链接条件,能够考虑使用union 代替

     

  • in 和 not in 也要慎用,对于连续的数值,能用 between 就不要用 in,exists 代替 in

     

  • 尽可能避免在 where 子句中对字段进行表达式操做和函数操做

 

关于数据类型

 

  • 尽可能使用数字型字段,若只含数值信息的字段尽可能不要设计为字符型,这会下降查询和链接的性能,并会增长存储开销。

     

  • 尽量的使用 varchar/nvarchar 代替 char/nchar ,由于变长字段存储空间小,对于查询来讲,在一个相对较小的字段内搜索效率显然要高些。

     

  • 最好不要给数据库留NULL,尽量的使用 NOT NULL填充数据库.备注、描述、评论之类的能够设置为 NULL,其余的,最好不要使用NULL。

     

  • 任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

 

关于临时表

 

  • 避免频繁建立和删除临时表,以减小系统表资源的消耗。对于一次性事件, 最好使用导出表。

     

  • 在新建临时表时,若是一次性插入数据量很大,那么可使用 select into 代替 create table,避免形成大量 log ,以提升速度;若是数据量不大,为了缓和系统表的资源,应先create table,而后insert。

     

  • 若是使用到了临时表,在最后将全部的临时表显式删除时,先 truncate table ,而后 drop table ,这样能够避免系统表的较长时间锁定。

 

关于索引

 

  • 先应考虑在 where 及 order by 涉及的列上创建索引。

     

  • 在使用索引字段做为条件时,若是该索引是复合索引,那么必须使用到该索引中的第一个字段做为条件 时才能保证系统使用该索引, 不然该索引将不会 被使用, 而且应尽量的让字段顺序与索引顺序相一致。

     

  • 索引并非越多越好,索引当然能够提升相应的 select 的效率,但同时也下降了 insert和update 的效率,由于 insert 或 update 时有可能会重建索引,因此视具体状况而定。一个表的索引数最好不要超过7个,若太多则应考虑一些不常使用到的列上建的索引是否有必要.

 

数据库架构调优

 

从底层来到了应用层,最终到架构层,然而脱离业务逻辑谈架构就是耍流氓。数据库架构一样是依赖业务系统的,稳定而又弹性地服务业务系统是关键。架构调优的方向有:

 

  • 分区分表

  • 业务分库

  • 主从同步与读写分离

  • 数据缓存

  • 主从热备与HA双活

  • …..

相关文章
相关标签/搜索