Mysql之性能优化

1.  硬件优化

    1.  CPU  8-16颗CPU

    2.  内存  96-128G 3-4实例  32G-64G  跑2个实例

    3.  硬盘  数量越多越好  性能:ssd(高并发) > sas(普通业务,线上) > sata(线下)

    4.  raid  RAID0>RAID10>RAID5>RAID1

    5.  网卡  千兆网卡还是万兆网卡

2.  软件优化

    1.  操作系统  64位系统

    2.  mysql  编译安装,编译优化

    3.  操作系统参数优化       

net.ipv4.tcp_fin_timeout = 2
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_keepalive_time =600
net.ipv4.ip_local_port_range = 4000 65000
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
net.core.somaxconn = 16384
net.core.netdev_max_backlog = 16384
net.ipv4.tcp_max_orphans = 16384

vm.swappiness=0      //尽量不使用swap
vm.dirty_backgroud_ratio=5-10  //5到10区间的数值
vm.dirty_ratio=10-20          //上面的值的两倍 将操作系统的脏数据刷到磁盘

    4.  my.cnf配置文件

[client]
port = 3306
# 客户端端口号为3306
socket = /data/3306/mysql.sock
default-character-set = utf8
# 客户端字符集,(控制character_set_client、character_set_connection、character_set_results)
[mysql]
no-auto-rehash
# 仅仅允许使用键值的updates和deletes
[mysqld]
# 组包括了mysqld服务启动的参数,它涉及的方面很多,其中有MySQL的目录和文件,通信、网络、信息安全,内存管理、优化、查询缓存区,还有MySQL日志设置等。
user = mysql
# mysql_safe脚本使用MySQL运行用户(编译时--user=mysql指定),推荐使用mysql用户。
port = 3306
# MySQL服务运行时的端口号。建议更改默认端口,默认容易遭受攻击。
socket = /data/3306/mysql.sock
# socket文件是在Linux/Unix环境下特有的,用户在Linux/Unix环境下客户端连接可以不通过TCP/IP网络而直接使用unix socket连接MySQL。
basedir = /application/mysql
# mysql程序所存放路径,常用于存放mysql启动、配置文件、日志等
datadir = /data/3306/data
# MySQL数据存放文件(极其重要)
character-set-server = utf8
# 数据库和数据库表的默认字符集。(推荐utf8,以免导致乱码)
log-error=/data/3306/mysql.err
# mysql错误日志存放路径及名称(启动出现错误一定要看错误日志,百分之百都能通过错误日志排插解决。)
pid-file=/data/3306/mysql.pid
# MySQL_pid文件记录的是当前mysqld进程的pid,pid亦即ProcessID。
skip-locking
# 避免MySQL的外部锁定,减少出错几率,增强稳定性。
skip-name-resolv
# 禁止MySQL对外部连接进行DNS解析,使用这一选项可以消除MySQL进行DNS解析的时候。但是需要注意的是,如果开启该选项,则所有远程主机连接授权都要使用IP地址方式了,否则MySQL将无法正常处理连接请求!
skip-networking
# 开启该选项可以彻底关闭MySQL的TCP/IP连接方式,如果Web服务器是以远程连接的方式访问MySQL数据库服务器的,则不要开启该选项,否则无法正常连接!
open_files_limit = 1024
# MySQLd能打开文件的最大个数,如果出现too mant open files之类的就需要调整该值了。
back_log = 384
# back_log参数是值指出在MySQL暂时停止响应新请求之前,短时间内的多少个请求可以被存在堆栈中。如果系统在短时间内有很多连接,则需要增加该参数的值,该参数值指定到来的TCP/IP连接的监听队列的大小。不同的操作系统在这个队列的大小上有自己的限制。如果试图将back_log设置得高于操作系统的限制将是无效的,其默认值为50.对于Linux系统而言,推荐设置为小于512的整数。
max_connections = 800
# 指定MySQL允许的最大连接进程数。如果在访问博客时经常出现 Too Many Connections的错误提示,则需要增大该参数值。
max_connect_errors = 6000
# 设置每个主机的连接请求异常中断的最大次数,当超过该次数,MySQL服务器将禁止host的连接请求,直到MySQL服务器重启或通过flush hosts命令清空此host的相关信息。
wait_timeout = 120
# 指定一个请求的最大连接时间,对于4GB左右内存的服务器来说,可以将其设置为5~10。
table_cache = 614K
# table_cache指示表高速缓冲区的大小。当MySQL访问一个表时,如果在MySQL缓冲区还有空间,那么这个表就被打开并放入表缓冲区,这样做的好处是可以更快速地访问表中的内容。一般来说,可以查看数据库运行峰值时间的状态值Open_tables和Open_tables,用以判断是否需要增加table_cache的值,即如果Open_tables接近table_cache的时候,并且Opened_tables这个值在逐步增加,那就要考虑增加这个值的大小了。
external-locking = FALSE
# MySQL选项可以避免外部锁定。True为开启。
max_allowed_packet =16M
# 服务器一次能处理最大的查询包的值,也是服务器程序能够处理的最大查询
sort_buffer_size = 1M
# 设置查询排序时所能使用的缓冲区大小,系统默认大小为2MB。
# 注意:该参数对应的分配内存是每个连接独占的,如果有100个连接,那么实际分配的总排序缓冲区大小为100 x6=600MB。所以,对于内存在4GB左右的服务器来说,推荐将其设置为6MB~8MB
join_buffer_size = 8M
# 联合查询操作所能使用的缓冲区大小,和sort_buffer_size一样,该参数对应的分配内存也是每个连接独享。
thread_cache_size = 64
# 设置Thread Cache池中可以缓存的连接线程最大数量,可设置为0~16384,默认为0.这个值表示可以重新利用保存在缓存中线程的数量,当断开连接时如果缓存中还有空间,那么客户端的线程将被放到缓存中;如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多线程,增加这个值可以改善系统性能。通过比较Connections和Threads_created状态的变量,可以看到这个变量的作用。我们可以根据物理内存设置规则如下:1GB内存我们配置为8,2GB内存我们配置为16,3GB我们配置为32,4GB或4GB以上我们给此值为64或更大的值。
thread_concurrency = 8
# 该参数取值为服务器逻辑CPU数量x 2,在本例中,服务器有两个物理CPU,而每个物理CPU又支持H.T超线程,所以实际取值为4 x 2 = 8。这也是双四核主流服务器的配置。
query_cache_size = 64M
# 指定MySQL查询缓冲区的大小。可以通过在MySQL控制台观察,如果Qcache_lowmem_prunes的值非常大,则表明经常出现缓冲不够的情况;如果Qcache_hits的值非常大,则表明查询缓冲使用得非常频繁。另外如果改值较小反而会影响效率,那么可以考虑不用查询缓冲。对于Qcache_free_blocks,如果该值非常大,则表明缓冲区中碎片很多。
query_cache_limit = 2M
# 只有小于此设置值的结果才会被缓存
query_cache_min_res_unit = 2k
# 设置查询缓存分配内存的最小单位,要适当第设置此参数,可以做到为减少内存快的申请和分配次数,但是设置过大可能导致内存碎片数值上升。默认值为4K,建议设置为1K~16K。
default_table_type = InnoDB
# 默认表的类型为InnoDB
thread_stack = 256K
# 设置MySQL每个线程的堆栈大小,默认值足够大,可满足普通操作。可设置范围为128KB至4GB,默认为192KB
#transaction_isolation = Level
# 数据库隔离级别 (READ UNCOMMITTED(读取未提交内容) READ COMMITTED(读取提交内容) REPEATABLE
READ(可重读) SERIALIZABLE(可串行化))
tmp_table_size = 64M
# 设置内存临时表最大值。如果超过该值,则会将临时表写入磁盘,其范围1KB到4GB。
max_heap_table_size = 64M
# 独立的内存表所允许的最大容量。
table_cache = 614
# 给经常访问的表分配的内存,物理内存越大,设置就越大。调大这个值,一般情况下可以降低磁盘IO,但相应的会占用更多的内存,这里设置为614。
table_open_cache = 512
# 设置表高速缓存的数目。每个连接进来,都会至少打开一个表缓存。因此, table_cache 的大小应与 max_connections 的设置有关。例如,对于 200 个并行运行的连接,应该让表的缓存至少有 200 × N ,这里 N 是应用可以执行的查询的一个联接中表的最大数量。此外,还需要为临时表和文件保留一些额外的文件描述符。
long_query_time = 1
# 慢查询的执行用时上限,默认设置是10s,推荐(1s~2s)
log_long_format
# 没有使用索引的查询也会被记录。(推荐,根据业务来调整)
log-slow-queries = /data/3306/slow.log
# 慢查询日志文件路径(如果开启慢查询,建议打开此日志)
log-bin = /data/3306/mysql-bin
# logbin数据库的操作日志,例如update、delete、create等都会存储到binlog日志,通过logbin可以实现增量恢复
relay-log = /data/3306/relay-bin
# relay-log日志记录的是从服务器I/O线程将主服务器的二进制日志读取过来记录到从服务器本地文件,然后SQL线程会读取relay-log日志的内容并应用到从服务器
relay-log-info-file = /data/3306/relay-log.info
# 从服务器用于记录中继日志相关信息的文件,默认名为数据目录中的relay-log.info。
binlog_cache_size = 4M
# 在一个事务中binlog为了记录sql状态所持有的cache大小,如果你经常使用大的,多声明的事务,可以增加此值来获取更大的性能,所有从事务来的状态都被缓冲在binlog缓冲中,然后再提交后一次性写入到binlog中,如果事务比此值大,会使用磁盘上的临时文件来替代,此缓冲在每个链接的事务第一次更新状态时被创建。
max_binlog_cache_size = 8M
# 最大的二进制Cache日志缓冲尺寸。
max_binlog_size = 1G
# 二进制日志文件的最大长度(默认设置1GB)一个二进制文件信息超过了这个最大长度之前,MySQL服务器会自动提供一个新的二进制日志文件接续上。
expire_logs_days = 7
# 超过7天的binlog,mysql程序自动删除(如果数据重要,建议不要开启该选项)
key_buffer_size = 256M
# 指定用于索引的缓冲区大小,增加它可得到更好的索引处理性能。对于内存在4GB左右的服务器来说,该参数可设置为256MB或384MB。
# 注意:如果该参数值设置得过大反而会使服务器的整体效率降低!
read_buffer_size = 4M
# 读查询操作所能使用的缓冲区大小。和sort_buffer_size一样,该参数对应的分配内存也是每个连接独享。
read_rnd_buffer_size = 16M
# 设置进行随机读的时候所使用的缓冲区。此参数和read_buffer_size所设置的Buffer相反,一个是顺序读的时候使用,一个是随机读的时候使用。但是两者都是针对与线程的设置,每个线程都可以产生两种Buffer中的任何一个。默认值256KB,最大值4GB。
bulk_insert_buffer_size = 8M
# 如果经常性的需要使用批量插入的特殊语句来插入数据,可以适当调整参数至16MB~32MB,建议8MB。
myisam_sort_buffer_size = 8M
# 设置在REPAIR Table或用Create index创建索引或 Alter table的过程中排序索引所分配的缓冲区大小,可设置范围4Bytes至4GB,默认为8MB
lower_case_table_names = 1
# 实现MySQL不区分大小。(发开需求-建议开启)
slave-skip-errors = 1032,1062
# 从库可以跳过的错误数字值(mysql错误以数字代码反馈,全的mysql错误代码大全,以后会发布至博客)。
replicate-ignore-db=mysql
# 在做主从的情况下,设置不需要同步的库。
server-id = 1
# 表示本机的序列号为1,如果做主从,或者多实例,serverid一定不能相同。
myisam_sort_buffer_size = 128M
# 当需要对于执行REPAIR, OPTIMIZE, ALTER 语句重建索引时,MySQL会分配这个缓存,以及LOAD DATA INFILE会加载到一个新表,它会根据最大的配置认真的分配的每个线程。
myisam_max_sort_file_size = 10G
# 当重新建索引(REPAIR,ALTER,TABLE,或者LOAD,DATA,TNFILE)时,MySQL被允许使用临时文件的最大值。
myisam_repair_threads = 1
# 如果一个表拥有超过一个索引, MyISAM 可以通过并行排序使用超过一个线程去修复他们.
myisam_recover
# 自动检查和修复没有适当关闭的 MyISAM 表.
innodb_additional_mem_pool_size = 4M
# 用来设置InnoDB存储的数据目录信息和其他内部数据结构的内存池大小。应用程序里的表越多,你需要在这里面分配越多的内存。对于一个相对稳定的应用,这个参数的大小也是相对稳定的,也没有必要预留非常大的值。如果InnoDB用广了这个池内的内存,InnoDB开始从操作系统分配内存,并且往MySQL错误日志写警告信息。默认为1MB,当发现错误日志中已经有相关的警告信息时,就应该适当的增加该参数的大小。
innodb_buffer_pool_size = 64M
# InnoDB使用一个缓冲池来保存索引和原始数据,设置越大,在存取表里面数据时所需要的磁盘I/O越少。强烈建议不要武断地将InnoDB的Buffer Pool值配置为物理内存的50%~80%,应根据具体环境而定。
innodb_data_file_path = ibdata1:128M:autoextend
# 设置配置一个可扩展大小的尺寸为128MB的单独文件,名为ibdata1.没有给出文件的位置,所以默认的是在MySQL的数据目录内。
innodb_file_io_threads = 4
# InnoDB中的文件I/O线程。通常设置为4,如果是windows可以设置更大的值以提高磁盘I/O
innodb_thread_concurrency = 8
# 你的服务器有几个CPU就设置为几,建议用默认设置,一般设为8。
innodb_flush_log_at_trx_commit = 1
# 设置为0就等于innodb_log_buffer_size队列满后在统一存储,默认为1,也是最安全的设置。
innodb_log_buffer_size = 2M
# 默认为1MB,通常设置为8~16MB就足够了。
innodb_log_file_size = 32M
# 确定日志文件的大小,更大的设置可以提高性能,但也会增加恢复数据库的时间。
innodb_log_files_in_group = 3
# 为提高性能,MySQL可以以循环方式将日志文件写到多个文件。推荐设置为3。
innodb_max_dirty_pages_pct = 90
# InnoDB主线程刷新缓存池中的数据。
innodb_lock_wait_timeout = 120
# InnoDB事务被回滚之前可以等待一个锁定的超时秒数。InnoDB在它自己的锁定表中自动检测事务死锁并且回滚事务。InnoDB用locak tables 语句注意到锁定设置。默认值是50秒。
innodb_file_per_table = 0
# InnoDB为独立表空间模式,每个数据库的每个表都会生成一个数据空间。0关闭,1开启。
# 独立表空间优点:
# 1、每个表都有自己独立的表空间。
# 2 、每个表的数据和索引都会存在自己的表空间中。
# 3、可以实现单表在不同的数据库中移动。
# 4、空间可以回收(除drop table操作处,表空不能自己回收。)

    5.  参数优化

        1.  Mysql缓存变量介绍及修改

            1.  全局缓存

                1.  innodb_buffer_pool_size  表示InnoDB类型的表和索引的最大缓存,配置到物理内存30~50%。查看该值show variables like 'innodb_buffer_pool_size';

innodb_buffer_pool_size:主要针对InnoDB表性能影响最大的一个参数。功能与Key_buffer_size一样。InnoDB占用的内存,除innodb_buffer_pool_size用于存储页面缓存数据外,另外正常情况下还有大约8%的开销,主要用在每个缓存页帧的描述、adaptive hash等数据结构,如果不是安全关闭,启动时还要恢复的话,还要另开大约12%的内存用于恢复,两者相加就有差不多21%的开销。假设:12G的innodb_buffer_pool_size,最多的时候InnoDB就可能占用到14.5G的内存。若系统只有16G,而且只运行MySQL,且MySQL只用InnoDB,

那么为MySQL开12G,是最大限度地利用内存了。

另外InnoDB和 MyISAM 存储引擎不同, MyISAM 的 key_buffer_size 只能缓存索引键,而 innodb_buffer_pool_size 却可以缓存数据块和索引键。适当的增加这个参数的大小,可以有效的减少 InnoDB 类型的表的磁盘 I/O 。

当我们操作一个 InnoDB 表的时候,返回的所有数据或者去数据过程中用到的任何一个索引块,都会在这个内存区域中走一遭。

可以通过 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 计算缓存命中率,并根据命中率来调整 innodb_buffer_pool_size 参数大小进行优化。值可以用以下命令查得:show status like 'Innodb_buffer_pool_read%';

比如查看当前系统中系统中

| Innodb_buffer_pool_read_requests      | 1283826 |

| Innodb_buffer_pool_reads              | 519     |

+---------------------------------------+---------+

其命中率99.959%=(1283826-519)/1283826*100%  命中率越高越好。
Mysql5.7之前,必须修改my.cnf文件
Mysql5.7之后,可以动态调整
  set global innodb_buffer_pool_size=4000000;

                2.  key_buffer_size  表示索引缓冲区的大小。索引缓冲区所有的线程共享。增加索引缓冲区可以得到更好处理的索引。当然,这个值也不是越大越好,它的大小取决于内存的大小。如果这个值太大,导致操作系统频繁换页,也会降低系统性能。查看该值show variables like 'key_buffer_size';      

key_buffer_size是用于索引块的缓冲区大小,增加它可得到更好处理的索引(对所有读和多重写),对MyISAM(MySQL表存储的一种类型,可以百度等查看详情)表性能影响最大的一个参数。如果你使它太大,系统将开始换页并且真的变慢了。严格说是它决定了数据库索引处理的速度,尤其是索引读的速度。对于内存在4GB左右的服务器该参数可设置为256M或384M.

怎么才能知道key_buffer_size的设置是否合理呢,一般可以检查状态值Key_read_requests和Key_reads   ,比例key_reads / key_read_requests应该尽可能的低,比如1:100,1:1000 ,1:10000。其值可以用以下命令查得:show status like 'key_read%';

比如查看系统当前key_read和key_read_request值为:

+-------------------+-------+

| Variable_name     | Value |

+-------------------+-------+

| Key_read_requests | 28535 |

| Key_reads         | 269   |

+-------------------+-------+

可知道有28535个请求,有269个请求在内存中没有找到直接从硬盘读取索引.

未命中缓存的概率为:0.94%=269/28535*100%.  一般未命中概率在0.1之下比较好。目前已远远大于0.1,证明效果不好。若命中率在0.01以下,则建议适当的修改key_buffer_size值。

http://dbahacker.com/mysql/innodb-myisam-compare(InnoDB与MyISAM的六大区别)

http://kb.cnblogs.com/page/99810/(查看存储引擎介绍)

MyISAM、InnoDB、MyISAM Merge引擎、InnoDB、memory(heap)、archive

                3.  innodb_additional_mem_pool_size  查看show variables like 'innodb_additional_mem_pool_size';    

innodb_additional_mem_pool_size 设置了InnoDB存储引擎用来存放数据字典信息以及一些内部数据结构的内存空间大小,所以当我们一个MySQL Instance中的数据库对象非常多的时候,是需要适当调整该参数的大小以确保所有数据都能存放在内存中提高访问效率的。

这个参数大小是否足够还是比较容易知道的,因为当过小的时候,MySQL会记录Warning信息到数据库的error log中,这时候你就知道该调整这个参数大小了。

查看当前系统mysql的error日志  cat  /var/lib/mysql/机器名.error 发现有很多waring警告。所以要调大为20M.

根据MySQL手册,对于2G内存的机器,推荐值是20M。

    32G内存的 100M

                4.  innodb_log_buffer_size(默认8M)  查看show variables like 'innodb_log_buffer_size';      

innodb_log_buffer_size  这是InnoDB存储引擎的事务日志所使用的缓冲区。类似于Binlog Buffer,InnoDB在写事务日志的时候,为了提高性能,也是先将信息写入Innofb Log Buffer中,当满足innodb_flush_log_trx_commit参数所设置的相应条件(或者日志缓冲区写满)之后,才会将日志写到文件 (或者同步到磁盘)中。可以通过innodb_log_buffer_size 参数设置其可以使用的最大内存空间。

   InnoDB 将日志写入日志磁盘文件前的缓冲大小。理想值为 1M 至 8M。大的日志缓冲允许事务运行时不需要将日志保存入磁盘而只到事务被提交(commit)。 因此,如果有大的事务处理,设置大的日志缓冲可以减少磁盘I/O。 在 my.cnf中以数字格式设置。

默认是8MB,系的如频繁的系统可适当增大至4MB~8MB。当然如上面介绍所说,这个参数实际上还和另外的flush参数相关。一般来说不建议超过32MB

注:innodb_flush_log_at_trx_commit参数对InnoDB Log的写入性能有非常关键的影响,默认值为1。该参数可以设置为0,1,2,解释如下:

0:log buffer中的数据将以每秒一次的频率写入到log file中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的commit并不会触发任何log buffer 到log file的刷新或者文件系统到磁盘的刷新操作;

1:在每次事务提交的时候将log buffer 中的数据都会写入到log file,同时也会触发文件系统到磁盘的同步;

2:事务提交会触发log buffer到log file的刷新,但并不会触发磁盘文件系统到磁盘的同步。此外,每秒会有一次文件系统到磁盘同步操作。

实际测试发现,该值对插入数据的速度影响非常大,设置为2时插入10000条记录只需要2秒,设置为0时只需要1秒,而设置为1时则需要229秒。因此,MySQL手册也建议尽量将插入操作合并成一个事务,这样可以大幅提高速度。根据MySQL手册,在存在丢失最近部分事务的危险的前提下,可以把该值设为0。

                5.  query_cache_size(默认32M)  查看该值show variables like 'query_cache_size';    

query_cache_size: 主要用来缓存MySQL中的ResultSet,也就是一条SQL语句执行的结果集,所以仅仅只能针对select语句。当我们打开了 Query Cache功能,MySQL在接受到一条select语句的请求后,如果该语句满足Query Cache的要求(未显式说明不允许使用Query Cache,或者已经显式申明需要使用Query Cache),MySQL会直接根据预先设定好的HASH算法将接受到的select语句以字符串方式进行hash,然后到Query Cache中直接查找是否已经缓存。也就是说,如果已经在缓存中,该select请求就会直接将数据返回,从而省略了后面所有的步骤(如SQL语句的解析,优化器优化以及向存储引擎请求数据等),极大的提高性能。根据MySQL用户手册,使用查询缓冲最多可以达到238%的效率。

当然,Query Cache也有一个致命的缺陷,那就是当某个表的数据有任何任何变化,都会导致所有引用了该表的select语句在Query Cache中的缓存数据失效。所以,当我们的数据变化非常频繁的情况下,使用Query Cache可能会得不偿失

   Query Cache的使用需要多个参数配合,其中最为关键的是query_cache_size和query_cache_type,前者设置用于缓存 ResultSet的内存大小,后者设置在何场景下使用Query Cache。在以往的经验来看,如果不是用来缓存基本不变的数据的MySQL数据库,query_cache_size一般256MB是一个比较合适的大小。当然,这可以通过计算Query Cache的命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))来进行调整。 query_cache_type可以设置为0(OFF),1(ON)或者2(DEMOND),分别表示完全不使用query cache,除显式要求不使用query cache(使用sql_no_cache)之外的所有的select都使用query cache,只有显示要求才使用query cache(使用sql_cache)。如果Qcache_lowmem_prunes的值非常大,则表明经常出现缓冲. 如果Qcache_hits的值也非常大,则表明查询缓冲使用非常频繁,此时需要增加缓冲大小;

根据命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))进行调整,一般不建议太大,256MB可能已经差不多了,大型的配置型静态数据可适当调大.

可以通过命令:show status like 'Qcache_%';查看目前系统Query catch使用大小

| Qcache_hits             | 1892463  |

| Qcache_inserts          | 35627  

命中率98.17%=1892463/(1892463 +35627 )*100           

            2.  局部缓存

                1.  read_buffer_size(默认2M)  查看该值show variables like 'read_buffer_size';

read_buffer_size 是MySql读入缓冲区大小。对表进行顺序扫描的请求将分配一个读入缓冲区,MySql会为它分配一段内存缓冲区。read_buffer_size变量控制这一

缓冲区的大小。如果对表的顺序扫描请求非常频繁,并且你认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能.

                2.  sort_buffer_size(默认2M)  查看该值show variables like 'sort_buffer_size';      

sort_buffer_size是MySql执行排序使用的缓冲大小。如果想要增加ORDER BY的速度,首先看是否可以让MySQL使用索引而不是额外的排序阶段。如果不能,可以尝试增加sort_buffer_size变量的大小                                 

                3.  read_rnd_buffer_size(8M)  查看该值show variables like 'read_rnd_buffer_size';

read_rnd_buffer_size 是MySql的随机读缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySql会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但MySql会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。

                4.  tmp_table_size(16M)  查看该值show variables like 'tmp_table_size';

 tmp_table_size是MySql的heap (堆积)表缓冲大小。所有联合在一个DML指令内完成,并且大多数联合甚至可以不用临时表即可以完成。大多数临时表是基于内存的(HEAP)表。具有大的记录长度的临时表 (所有列的长度的和)或包含BLOB列的表存储在硬盘上。如果某个内部heap(堆积)表大小超过tmp_table_size,MySQL可以根据需要自动将内存中的heap表改为基于硬盘的MyISAM表。还可以通过设置tmp_table_size选项来增加临时表的大小。也就是说,如果调高该值,MySql同时将增加heap表的大小,可达到提高
联接查询速度的效果。

                5.  record_buffer(128K)  查看该值show variables like 'record_buffer';  

record_buffer每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。如果你做很多顺序扫描,你可能想要增加该值。默认数值是131072(128K)

            3.  其它缓存

                1.  table_cache(默认值64)  查看该值show variables like 'table_open_cache%';

TABLE_CACHE(5.1.3及以后版本又名TABLE_OPEN_CACHE)

table_cache指定表高速缓存的大小。每当MySQL访问一个表时,如果在表缓冲区中还有空间,该表就被打开并放入其中,这样可以更快地访问表内容。通过检查峰值时间的状态值Open_tables和Opened_tables,可以决定是否需要增加table_cache的值。如果你发现open_tables等于table_cache,并且opened_tables在不断增长,那么你就需要增加table_cache的值了(上述状态值可以使用SHOW STATUS LIKE ‘Open%tables’获得)。注意,不能盲目地把table_cache设置成很大的值。如果设置得太高,可能会造成文件描述符不足,从而造成性能不稳定或者连接失败。

SHOW STATUS LIKE 'Open%tables';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| Open_tables   | 356   |

| Opened_tables | 0     |

+---------------+-------+

2 rows in set (0.00 sec)

open_tables表示当前打开的表缓存数,如果执行flush tables操作,则此系统会关闭一些当前没有使用的表缓存而使得此状态值减小;

opend_tables表示曾经打开的表缓存数,会一直进行累加,如果执行flush tables操作,值不会减小。

在mysql默认安装情况下,table_cache的值在2G内存以下的机器中的值默认时256到512,如果机器有4G内存,则默认这个值 是2048,但这决意味着机器内存越大,这个值应该越大,因为table_cache加大后,使得mysql对SQL响应的速度更快了,不可避免的会产生 更多的死锁(dead lock),这样反而使得数据库整个一套操作慢了下来,严重影响性能。所以平时维护中还是要根据库的实际情况去作出判断,找到最适合你维护的库的 table_cache值。

由于MySQL是多线程的机制,为了提高性能,每个线程都是独自打开自己需要的表的文件描 述符,而不是通过共享已经打开的.针对不同存储引擎处理的方法当然也不一样

在myisam表引擎中,数据文件的描述符 (descriptor)是不共享的,但是索引文件的描述符却是所有线程共享的.Innodb中和使用表空间类型有关,假如是共享表空间那么实际就一个数 据文件,当然占用的数据文件描述符就会比独立表空间少.
mysql手册上给的建议大小 是:table_cache=max_connections*n

n表示查询语句中最大表数, 还需要为临时表和文件保留一些额外的文件描述符。

这个数据遭到很多质疑,table_cache够用就好,检查 Opened_tables值,如果这个值很大,或增长很快那么你就得考虑加大table_cache了.

  table_cache:所有线程打开的表的数目。增大该值可以增加mysqld需要的文件描述符的数量。默认值是64. 

                2.  thread_cache_size(服务器线程缓存)

默认的thread_cache_size=8,但是看到好多配置的样例里的值一般是32,64,甚至是128,感觉这个参数对优化应该有帮助,于是查了下:
根据调查发现以上服务器线程缓存thread_cache_size没有进行设置,或者设置过小,这个值表示可以重新利用保存在缓存中线程的数量,当断开连接时如果缓存中还有空间,那么客户端的线程将被放到缓存中,如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多新的线程,增加这个值可以改善系统性能.通过比较 Connections 和 Threads_created 状态的变量,可以看到这个变量的作用。(–>表示要调整的值)   根据物理内存设置规则如下:
1G —> 8
2G —> 16
3G —> 32     >3G —> 64

  mysql> show status like 'thread%';
+——————-+——-+
| Variable_name     | Value |
+——————-+——-+
| Threads_cached    | 0     |  <—当前被缓存的空闲线程的数量
| Threads_connected | 1     |  <—正在使用(处于连接状态)的线程
| Threads_created   | 1498  |  <—服务启动以来,创建了多少个线程
| Threads_running   | 1     |  <—正在忙的线程(正在查询数据,传输数据等等操作)
+——————-+——-+

查看开机起来数据库被连接了多少次?

mysql> show status like '%connection%';
+———————-+——-+
| Variable_name        | Value |
+———————-+——-+
| Connections          | 1504  |          –>服务启动以来,历史连接数
| Max_used_connections | 2     |
+———————-+——-+

通过连接线程池的命中率来判断设置值是否合适?命中率超过90%以上,设定合理。

 (Connections -  Threads_created) / Connections * 100 %                       

        2.  关于日志方面

innodb_log_file_size
作用:指定在一个日志组中,每个log的大小。
结合innodb_buffer_pool_size设置其大小,25%-100%。避免不需要的刷新。
注意:这个值分配的大小和数据库的写入速度,事务大小,异常重启后的恢复有很大的关系。一般取256M可以兼顾性能和recovery的速度。
分配原则:几个日值成员大小加起来差不多和你的innodb_buffer_pool_size相等。上限为每个日值上限大小为4G.一般控制在几个Log文件相加大小在2G以内为佳。具体情况还需要看你的事务大小,数据大小为依据。
说明:这个值分配的大小和数据库的写入速度,事务大小,异常重启后的恢复有很大的关系。
设置方法:在my.cnf文件里:
innodb_log_file_size = 256M

innodb_log_files_in_group
作用:指定你有几个日值组。
分配原则: 一般我们可以用2-3个日值组。默认为两个。
设置方法:在my.cnf文件里:
innodb_log_files_in_group=3

innodb_log_buffer_size:
作用:事务在内存中的缓冲,也就是日志缓冲区的大小, 默认设置即可,具有大量事务的可以考虑设置为16M。
如果这个值增长过快,可以适当的增加innodb_log_buffer_size
另外如果你需要处理大理的TEXT,或是BLOB字段,可以考虑增加这个参数的值。
设置方法:在my.cnf文件里:
innodb_log_buffer_size=3M

innodb_flush_logs_at_trx_commit
作用:控制事务的提交方式,也就是控制log的刷新到磁盘的方式。
分配原则:这个参数只有3个值(0,1,2).默认为1,性能更高的可以设置为0或是2,这样可以适当的减少磁盘IO(但会丢失一秒钟的事务。),游戏库的MySQL建议设置为0。主库请不要更改了。
其中:
0:log buffer中的数据将以每秒一次的频率写入到log file中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的commit并不会触发任何log buffer 到log file的刷新或者文件系统到磁盘的刷新操作;
1:(默认为1)在每次事务提交的时候将logbuffer 中的数据都会写入到log file,同时也会触发文件系统到磁盘的同步;
2:事务提交会触发log buffer 到log file的刷新,但并不会触发磁盘文件系统到磁盘的同步。此外,每秒会有一次文件系统到磁盘同步操作。
说明:
这个参数的设置对Innodb的性能有很大的影响,所以在这里给多说明一下。
当这个值为1时:innodb 的事务LOG在每次提交后写入日值文件,并对日值做刷新到磁盘。这个可以做到不丢任何一个事务。
当这个值为2时:在每个提交,日志缓冲被写到文件,但不对日志文件做到磁盘操作的刷新,在对日志文件的刷新在值为2的情况也每秒发生一次。但需要注意的是,由于进程调用方面的问题,并不能保证每秒100%的发生。从而在性能上是最快的。但操作系统崩溃或掉电才会删除最后一秒的事务。
当这个值为0时:日志缓冲每秒一次地被写到日志文件,并且对日志文件做到磁盘操作的刷新,但是在一个事务提交不做任何操作。mysqld进程的崩溃会删除崩溃前最后一秒的事务。
从以上分析,当这个值不为1时,可以取得较好的性能,但遇到异常会有损失,所以需要根据自已的情况去衡量。
设置方法:在my.cnf文件里:
innodb_flush_logs_at_trx_commit=1

        3.  文件IO分配,空间占用方面

innodb_file_per_table
作用:使每个Innodb的表,有自已独立的表空间。如删除文件后可以回收那部分空间。默认是关闭的,建议打开(innodb_file_per_table=1)
分配原则:只有使用不使用。但DB还需要有一个公共的表空间。
设置方法:在my.cnf文件里:
innodb_file_per_table=1

innodb_file_io_threads
作用:文件读写IO数,这个参数只在Windows上起作用。在Linux上只会等于4,默认即可!
设置方法:在my.cnf文件里:
innodb_file_io_threads=4

innodb_open_files
作用:限制Innodb能打开的表的数据。
分配原则:这个值默认是300。如果库里的表特别多的情况,可以适当增大为1000。innodb_open_files的大小对InnoDB效率的影响比较小。但是在InnoDBcrash的情况下,innodb_open_files设置过小会影响recovery的效率。所以用InnoDB的时候还是把innodb_open_files放大一些比较合适。
设置方法:在my.cnf文件里:
innodb_open_files=800

innodb_data_file_path
指定表数据和索引存储的空间,可以是一个或者多个文件。最后一个数据文件必须是自动扩充的,也只有最后一个文件允许自动扩充。这样,当空间用完后,自动扩充数据文件就会自动增长(以8MB为单位)以容纳额外的数据。
例如: innodb_data_file_path=/disk1/ibdata1:900M;/disk2/ibdata2:50M:autoextend 两个数据文件放在不同的磁盘上。数据首先放在ibdata1 中,当达到900M以后,数据就放在ibdata2中。
设置方法,在my.cnf文件里:
innodb_data_file_path =ibdata1:1G;ibdata2:1G;ibdata3:1G;ibdata4:1G;ibdata5:1G;ibdata6:1G:autoextend

innodb_data_home_dir
放置表空间数据的目录,默认在mysql的数据目录,设置到和MySQL安装文件不同的分区可以提高性能。
设置方法,在my.cnf文件里:(比如mysql的数据目录是/data/mysql/data,这里可以设置到不通的分区/home/mysql下)
innodb_data_home_dir = /home/mysql

        4.  其他参数

innodb_flush_method
作用:Innodb和系统打交道的一个IO模型
分配原则:
Windows不用设置。
linux可以选择:O_DIRECT
直接写入磁盘,禁止系统Cache了
设置方法:在my.cnf文件里:
innodb_flush_method=O_DIRECT

innodb_max_dirty_pages_pct
作用:在buffer pool缓冲中,允许Innodb的脏页的百分比,值在范围1-100,默认为90,建议保持默认。
这个参数的另一个用处:当Innodb的内存分配过大,致使Swap占用严重时,可以适当的减小调整这个值,使达到Swap空间释放出来。建义:这个值最大在90%,最小在15%。太大,缓存中每次更新需要致换数据页太多,太小,放的数据页太小,更新操作太慢。
设置方法:在my.cnf文件里:
innodb_max_dirty_pages_pct=90
动态更改需要有管理员权限:
set global innodb_max_dirty_pages_pct=50;

innodb_thread_concurrency
同时在Innodb内核中处理的线程数量。建议默认值。
设置方法,在my.cnf文件里:
innodb_thread_concurrency = 16

        5.  公共参数

skip-external-locking
MyISAM存储引擎也同样会使用这个参数,MySQL4.0之后,这个值默认是开启的。
作用是避免MySQL的外部锁定(老版本的MySQL此参数叫做skip-locking),减少出错几率增强稳定性。建议默认值。
设置方法,在my.cnf文件里:
skip-external-locking

skip-name-resolve
禁止MySQL对外部连接进行DNS解析(默认是关闭此项设置的,即默认解析DNS),使用这一选项可以消除MySQL进行DNS解析的时间。
但需要注意,如果开启该选项,则所有远程主机连接授权都要使用IP地址方式,否则MySQL将无法正常处理连接请求!如果需要,可以设置此项。
设置方法,在my.cnf文件里:(我这线上mysql数据库中打开了这一设置)
skip-name-resolve

max_connections
设置最大连接(用户)数,每个连接MySQL的用户均算作一个连接,max_connections的默认值为100。此值需要根据具体的连接数峰值设定。
设置方法,在my.cnf文件里:
max_connections = 3000

query_cache_size
查询缓存大小,如果表的改动非常频繁,或者每次查询都不同,查询缓存的结果会减慢系统性能。可以设置为0。
设置方法,在my.cnf文件里:
query_cache_size = 512M

sort_buffer_size
connection级的参数,排序缓存大小。一般设置为2-4MB即可。
设置方法,在my.cnf文件里:
sort_buffer_size = 1024M
read_buffer_size
connection级的参数。一般设置为2-4MB即可。
设置方法,在my.cnf文件里:
read_buffer_size = 1024M

max_allowed_packet
网络包的大小,为避免出现较大的网络包错误,建议设置为16M
设置方法,在my.cnf文件里:
max_allowed_packet = 16M

table_open_cache
当某一连接访问一个表时,MySQL会检查当前已缓存表的数量。如果该表已经在缓存中打开,则会直接访问缓存中的表,以加快查询速度;如果该表未被缓存,则会将当前的表添加进缓存并进行查询。
通过检查峰值时间的状态值Open_tables和Opened_tables,可以决定是否需要增加table_open_cache的值。
如果发现open_tables等于table_open_cache,并且opened_tables在不断增长,那么就需要增加table_open_cache的值;设置为512即可满足需求。
设置方法,在my.cnf文件里:
table_open_cache = 512

myisam_sort_buffer_size
实际上这个myisam_sort_buffer_size参数意义不大,这是个字面上蒙人的参数,它用于ALTER TABLE, OPTIMIZE TABLE, REPAIR TABLE 等命令时需要的内存。默认值即可。
设置方法,在my.cnf文件里:
myisam_sort_buffer_size = 8M

thread_cache_size
线程缓存,如果一个客户端断开连接,这个线程就会被放到thread_cache_size中(缓冲池未满),SHOW STATUS LIKE 'threads%';如果 Threads_created 不断增大,那么当前值设置要改大,改到 Threads_connected 值左右。(通常情况下,这个值改善性能不大),默认8即可
设置方法,在my.cnf文件里:
thread_cache_size = 8

innodb_thread_concurrency
线程并发数,建议设置为CPU内核数*2
设置方法,在my.cnf文件里:
innodb_thread_concurrency = 8

key_buffer_size
仅作用于 MyISAM存储引擎,用来设置用于缓存 MyISAM存储引擎中索引文件的内存区域大小。如果我们有足够的内存,这个缓存区域最好是能够存放下我们所有的 MyISAM 引擎表的所有索引,以尽可能提高性能。不要设置超过可用内存的30%。即使不用MyISAM表,也要设置该值8-64M,用于临时表。
设置方法,在my.cnf文件里:
key_buffer_size = 8M

        6.  back_log=500  

back_log值指出在MySQL暂时停止回答新请求之前的短时间内多少个请求可以被存在堆栈中。也就是说,如果MySql的连接数据达到max_connections时,新来的请求将会被存在堆栈中,以等待某一连接释放资源,该堆栈的数量即back_log,如果等待连接的数量超过back_log,将不被授予连接资源。将会报:unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待连接进程时.

back_log值不能超过TCP/IP连接的侦听队列的大小。若超过则无效,查看当前系统的TCP/IP连接的侦听队列的大小命令:cat /proc/sys/net/ipv4/tcp_max_syn_backlog目前系统为1024。对于Linux系统推荐设置为小于512的整数。

修改系统内核参数,)http://www.51testing.com/html/64/n-810764.html

查看mysql 当前系统默认back_log值,命令:

show variables like 'back_log'; 查看当前数量   

        7.  wait_timeout  表示服务器在关闭一个连接时等待行动的秒数。默认值是28800

我对wait-timeout这个参数的理解:MySQL客户端的数据库连接闲置最大时间值。

说得比较通俗一点,就是当你的MySQL连接闲置超过一定时间后将会被强行关闭。MySQL默认的wait-timeout  值为8个小时,可以通过命令show variables like 'wait_timeout'查看结果值;。

设置这个值是非常有意义的,比如你的网站有大量的MySQL链接请求(每个MySQL连接都是要内存资源开销的 ),由于你的程序的原因有大量的连接请求空闲啥事也不干,白白占用内存资源,或者导致MySQL超过最大连接数从来无法新建连接导致“Too many connections”的错误。在设置之前你可以查看一下你的MYSQL的状态(可用show processlist),如果经常发现MYSQL中有大量的Sleep进程,则需要 修改wait-timeout值了。

interactive_timeout:服务器关闭交互式连接前等待活动的秒数。交互式客户端定义为在mysql_real_connect()中使用CLIENT_INTERACTIVE选项的客户端。可以通过命令show variables like 'interactive_timeout'查看结果

wait_timeout:服务器关闭非交互连接之前等待活动的秒数。在线程启动时,根据全局wait_timeout值或全局 interactive_timeout值初始化会话wait_timeout值,取决于客户端类型(由mysql_real_connect()的连接选项CLIENT_INTERACTIVE定义).

这两个参数必须配合使用。否则单独设置wait_timeout无效   

    4.  优化查询

        1.  分析查询语句  

            1.  使用EXPLAIN语句

                可以参考这篇文章  https://www.cnblogs.com/yangjianbo/articles/8698993.html

            2.  使用DESCRIBE语句

                describe  select语句

                显示内容与explain一模一样

        2.  使用索引进行查询

        3.  优化子查询

            使用join来代替子查询

    5.  优化数据库结构

        1.  将字段很多的表分解成多个表 

        2.  增加中间表

        3.  优化插入记录的速度

            1.  对于MyISAM引擎的表

                1.  禁用索引

                    ALTER TABLE table_name DISABLE KEYS;  禁用索引

                    ALTER TABLE table_name ENABLE KEYS;  启用索引

                2.  禁用唯一性检查

                    SET UNIQUE_CHECKS=0;  禁用唯一性检查

                    SET UNIQUE_CHECKS=1;  开启唯一性检查

                3.  使用批量插入

                    可以逐条插入,也可以一条插入多条数据,后者更快。

                4.  使用LOAD DATA INFILE批量导入  

            2.  对于Innodb引擎的表     

                1.  禁用唯一性检查

                    SET UNIQUE_CHECKS=0;  禁用唯一性检查

                    SET UNIQUE_CHECKS=1;  开启唯一性检查

                2.  禁用外键检查

                    SET foreign_key_checks=0;  禁用外键检查  

                    SET foreign_key_checks=1;  启用外键检查

                3.  禁用自动提交

                    set autocommit=0;  禁止自动提交

                    set autocommit=1;  启动自动提交

        4.  分析表,检查表和优化表

            1.  分析表

                1.  基本语法

                    ANALYZE [LOCAL| NO_WRITE_TO_BINLOG]  TABLE tbl_name  数据库系统会自动对表加一个只读锁

                2.  案例分析                    

mysql> analyze table students;
+---------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------------------+---------+----------+----------+
| yangjianbo.students | analyze | status | OK |
+---------------------+---------+----------+----------+ 

Table:  表示分析的表的名称

Op:  表示执行的操作

Msg_type:  表示信息类型

Msg_text:  显示信息                                                      

            2.  检查表

                1.  基本语法

                    CHECK TABLE tbl_name [option= {QUICK|FAST|MEDIUM|EXTENDED|CHANGED}]  option只对MyISAM类型的表有效,执行过程中会给表加上只读锁

            3.  优化表

                查看表碎片                 

select TABLE_SCHEMA,TABLE_NAME,ENGINE,concat(splinter,'G') '碎片(G)' from (SELECT TABLE_SCHEMA,TABLE_NAME,ENGINE,ROUND((DATA_LENGTH+INDEX_LENGTH-TABLE_ROWS*AVG_ROW_LENGTH)/1024/1024/1024) splinter from information_schema.`TABLES` )a order by splinter desc; 

                OPTIMIZE [LOCAL|NO_WRITE_TO_BINLOG] TABLE tbl_name 

                OPTIMIZE TABLE语句可以消除删除和更新造成的文件碎片,在执行过程中会给表加上只读锁         

        5.  大的复杂的sql语句拆分成多个小的sql语句

        6.  show profiles

            1.  mysql提供用来分析当前会话中语句执行的资源消耗情况。默认情况下,参数处于关闭状态,并保存最近15次的运行结果。

            2.  查看profiles的状态。show variables like "%profil%";

            3.  开启profiles,set profiling=1;

            4.  结果分析,show profiles;

                

 

                show profile cpu,block io for query  4;

                

                需要注意的status。常见有:

                converting HEAP to MyISAM 查询结果太大,内存不够用往磁盘上复制

                creating tmp table 创建临时表

                copying to tmp tlabe on disk  把数据复制到临时表,危险

                  结果查找资料后 了解到 发现mysql可以通过变量tmp_table_size和max_heap_table_size来控制内存表大小上限,如果超过上限会将数据写到磁盘上,从而会有物理磁盘的读写操作,导致影响性能。

                locked               

    6.  架构的优化

    7.  流程制度安全优化

posted @ 2021-06-21 10:58  奋斗史  阅读(102)  评论(0)    收藏  举报