MySQL优化系列之一
Posted kankankankankan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL优化系列之一相关的知识,希望对你有一定的参考价值。
mysql数据库常见的两个瓶颈是CPU和I/O。 CPU在饱和的情况下一般发生在数据装入内存或者从磁盘上读取数据的时候,当装入的数据远大于
内存容量的时候,这时可能会发生I/O瓶颈, 如果是分布式应用的话,当查询量大的时候瓶颈可能会出现在网络上。 我们可以采用常用的Linux
命令来查看系统的性能状态。
1、mpstat 系统监控工具,CPU的统计信息,这些信息存放在/proc/stat文件中,同样也适用于多CPU系统。mpstat命令可查看多核CPU
每个计算核心的统计数据。
2、vmstat 也是一种监控工具,可以显示在给定的时间间隔内服务器的状态信息,包括CPU使用率、内存使用、虚拟内存交换情况,IO读写情况。
3、iostat 监控设备的IO负载情况
4、sar 文件的读写情况、系统调用使用情况、磁盘I/O、CPU效率、内存使用状况、进程活动及IPC(进程间通信)有关活动
5、top 系统中各个进程的资源占用状况,该命令将独占前台,直到用户终止该程序为止。该命令提供了实时对系统处理器的状态监视
查询与索引分析方法及优化方式
常见分析手段有慢查询日志、explain分析查询、profiling分析以及show命令及系统变量
show status 显示状态信息 show status like ‘xxx‘
show variables 先系统变量 show variable like ‘xxx‘
show innodb status 显示innodb存储引擎的状态
show processlist 查看当前SQL执行 包括执行状态、是否锁表等
mysqladmin variables -u xxx -p xxx 显示系统变量
mysqladmin extended-status -u xxx -p xxx 显示状态信息
慢查询日志分析
慢日志查询开启方法: 在配置文件my.cnf或者my.ini中的mysqld下面一行加入两个配置参数
log-slow-queries=/data/myssqldata/show-query.log //慢查询日志存放位置
long_query_time=2 //设置查询超时时间
log-queries-not-using-indexes //记录没有使用索引的查询
explain 字段属性说明
table 显示这行数据是关于哪张表
possible_keys 显示可能应用在这张表中的索引。如果为空,没有可能的索引
key 实际使用的索引,如果为null 则没有使用索引
key_len 使用索引的长度,在不损失精确性的前提下,长度越短越好
ref 显示索引哪一列被使用了,如果可能的话,是一个常数
rows 返回请求数据的行数
type 显示查询使用了哪一种类型,从最好到最差的连接类型。
system const : 二者将查询的变量转为常量
eq_reg : 访问索引,返回某单一行的数据,通常在连接查询时出现
reg : 访问索引,返回某个值的数据,通常使用等号的时候发生
range : 这个类型使用索引返回一个范围中的行,比如使用大于或小于查询条件,并且该字段上建有索引
index : 以索引的顺序进行全表扫描,优点是不用排序,缺点全表扫描
all : 全表扫描,尽量避免
extra 解析查询额外信息
using index 只用到索引,可以避免访问表
using where 使用where过滤数据
using temporary 用到了临时表
using filesort 用到了额外的排序 order by xxx 没有使用到索引的时候,就会使用额外的排序
profiling 可以得到更准确的SQL执行消耗系统资源的信息, profiling默认是关闭的,打开 set profiling=1;
索引类型
普通索引:这是基本的索引类型,没有唯一性之类的限制
唯一性索引:所用的索引列值保持唯一性
主键: 是一种唯一索引,指定 promary key
全文索引: MySQL从3.23.23版本开始支持全文索引和全文检索。全文索引类型为fulltext 可以在varchar或者text类型上创建
单列索引和多列索引(复合索引)
多列索引有一个特点,即最左前缀。假如一个多列索引为key(x y z)。当搜索条件是以下各种列的的组合和顺序时,MySQL才会使用多列索引 x,y,z x,y x
建立索引的建议
1、越小的数据类型通常更好,因为越小的数据类型通常在磁盘、内存和CPU缓存中都需要更少的空间,处理起来更快
2、简单的数据类型更好,整型数据比起字符,处理开销更小,因为字符串的比较更复杂。在MySQL中,应该使用内置的日期
和时间数据类型,而不是用字符串存储时间。以及用整型数据类型存储IP地址
3、避免null 应该指定列为not null。在MySQL中,含有空值的列很难进行查询优化。应该使用0、特殊值、空串代替空值
设置索引和编写SQL的一些小建议
1、当结果集只有一行数据时使用limit 1
2、避免select *
3、使用连接join代替子查询
4、使用enum\char而不是varchar,使用合理的字段属性长度
5、尽可能使用 not null
6、固定长度的表会更快
7、拆分大的delete或insert语句
8、查询的列越小越快
where的使用
尽量在多个条件的时候,把会提取尽量少数据量的条件放在前面,减少后一个where条件的查询时间
索引无效情况
1、where子句查询条件有 !=
2、where子句使用了函数 select * from tb where left(xxx, 4) = ‘yyyy‘
3、使用like查询 %xxx%
MySQL内部配置优化
1、连接请求的变量 max_connections 。 如果服务器的并发连接请求量比较大,建议改大点。但不要盲目提高,MySQL会为
每个连接提供连接缓冲区,就会开销越多的内存。
show variables like ‘max_connections‘ show status like ‘max_used_connections‘
max_used_connections / max_connections * 100% 85为理想值
2、back_log: 当MySQL的连接数达到max_connections时,新来的请求会存放在堆栈中,以等待某一链接被释放资源,该堆栈的数量
即为back_log,如果等待连接的数量超过back_log,将不被授予连接资源。 默认值为50,可设置为128.
3、interactive_timeout:一个交互连接在被服务器在关闭钱等待行动的秒数。 默认值28800,可设置为7200
4、key_buffer_size:全局缓冲区大小,决定了索引的处理速度。 可通过检查状态值key_read_requests和key_reads。 key_reads /
key_read_requests应该尽可能的低,至少是1:100
5、query_cache_size 查询缓冲,将查询结果存放在缓冲区。 通过检查状态值Qcache_*,可知道query_cache_size设置是否合理。
如果Qcache_lowmem_prunes的值非常大,则表明经常出现缓冲不够的情况,如果Qcache_hits的值也非常大,则表明查询缓冲使用
非常频繁,此事需要增加缓冲大小
6、innodb_buffer_pool_size 作用相当于key_buffer_size对于MyISAM表一样。
7、innodb_flush_log_at_trx_commit: 控制innodb将log buffer中的数据写入日志文件并flush磁盘的时间点,取值分别为 0 1 2
0代表当事务提交时,不做日志写入操作,而是每秒将log buffer中的数据写入日志文件病flush磁盘一次
1代表每秒或每次事务的提交都会引起日志文件写入、flush磁盘的操作、确保了事务的acid
2代表每次事务提交引起写入日志文件的动作,但每秒完成一次flush磁盘操作
根据MySQL手册,在允许丢失最近部分事务的前提下,可以设置为0或2
8、innodb_log_buffer_size: log缓存大小,一般为1-8M,默认为1M,对于较大事务可以增大缓存大小,设置为4或8
每个连接的缓冲
1)record_buffer_size
每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。如果你做很多顺序扫描,你可能想要增加该值。
默认数值是131072(128K),可改为16773120 (16M)
2)read_rnd_buffer_size
随机读缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySQL会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但MySQL会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。
一般可设置为16M
3) sort_buffer_size
每个需要进行排序的线程分配该大小的一个缓冲区。增加这值加速ORDER BY或GROUP BY操作。
默认数值是2097144(2M),可改为16777208 (16M)。
4) join_buffer_size
联合查询操作所能使用的缓冲区大小
record_buffer_size,read_rnd_buffer_size,sort_buffer_size,join_buffer_size为每个线程独占,也就是说,如果有100个线程连接,则占用为16M*100
5) table_cache
表高速缓存的大小。每当MySQL访问一个表时,如果在表缓冲区中还有空间,该表就被打开并放入其中,这样可以更快地访问表内容。通过检查峰值时间的状态值Open_tables和Opened_tables,可以决定是否需要增加table_cache的值。如果你发现open_tables等于table_cache,并且opened_tables在不断增长,那么你就需要增加table_cache的值了(上述状态值可以使用SHOW STATUS LIKE ‘Open%tables’获得)。注意,不能盲目地把table_cache设置成很大的值。如果设置得太高,可能会造成文件描述符不足,从而造成性能不稳定或者连接失败。
1G内存机器,推荐值是128-256。内存在4GB左右的服务器该参数可设置为256M或384M。
6) max_heap_table_size
用户可以创建的内存表(memory table)的大小。这个值用来计算内存表的最大行数值。这个变量支持动态改变,即set @max_heap_table_size=#
这个变量和tmp_table_size一起限制了内部内存表的大小。如果某个内部heap(堆积)表大小超过tmp_table_size,MySQL可以根据需要自动将内存中的heap表改为基于硬盘的MyISAM表。
7)tmp_table_size
通过设置tmp_table_size选项来增加一张临时表的大小,例如做高级GROUP BY操作生成的临时表。如果调高该值,MySQL同时将增加heap表的大小,可达到提高联接查询速度的效果,建议尽量优化查询,要确保查询过程中生成的临时表在内存中,避免临时表过大导致生成基于硬盘的MyISAM表。
8)thread_cache_size
可以复用的保存在中的线程的数量。如果有,新的线程从缓存中取得,当断开连接的时候如果有空间,客户的线置在缓存中。如果有很多新的线程,为了提高性能可以这个变量值。
通过比较 Connections和Threads_created状态的变量,可以看到这个变量的作用。
默认值为110,可调优为80。
9) thread_concurrency
推荐设置为服务器 CPU核数的2倍,例如双核的CPU, 那么thread_concurrency的应该为4;2个双核的cpu, thread_concurrency的值应为8。默认为8
10)wait_timeout
指定一个请求的最大连接时间,对于4GB左右内存的服务器可以设置为5-10。
以上是关于MySQL优化系列之一的主要内容,如果未能解决你的问题,请参考以下文章