一.慢查询日志开启方法:
1.查看是否开启慢查询日志 show variables like 'slow_query_log'
2.设置没有索引的记录到慢查询日志 set global log_queries_not_using_indexes=on
3.查看超过多长时间的sql进行记录到慢查询日志 show variables like 'long_query_time'
4.设置慢查询的时间 set long_query_time=1
5.windows环境下可以直接修改my.ini文件。设置超时记录慢查询时间修改后需要重启数据库生效。
二.慢查询日志分析
两款mysql慢查询日志分析工具,一款是MySQL自带的mysqldumpslow,另一款是pt-query-digest;推荐使用pt-query-digest,分析日志更具体。
通过pt-query-digest日志发现有问题的sql:
1.查询次数多且每次占用查询时间长的sql。通过日志的前几个查询
如图查询了1次,占用73%的时间。
2.IO大的SQL。数据库主要瓶颈是IO,对IO进行优化,可以有效提高数据库的效率。通过日志可以分析Rows examine项,扫描行数的多少,扫描越多,IO消耗越大。
3.未命中索引的sql。通过分析日志的Rows examine与Rows sent的比,比值越大,说明扫描的行数多,发送数据行数少,没有使用索引,而进行表的扫描。
三.explain查询计划
使用expain查询sql的执行计划,explain返回各列的含义
table:显示这一行的数据是关于哪张表的
type:这是重要的列,显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、index和ALL
possible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。
key:实际使用的索引。如果为NULL,则没有使用索引。
key_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好。
ref:显示索引的哪一列被使用了,如果可能的话,是一个常数
rows:MYSQL认为必须检查的用来返回请求数据的行数
extra列需要注意的返回值
Using filesort:看到这个的时候,查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行
Using temporary:看到这个的时候,查询需要优化了。这里,MYSQL徐哟创建一个临时表来存储接口,这通常发生在对不同的列表进行ORDER BY上,而不是GROUP BY上
四.sql优化
1.在使用max()函数时,可以给查询列,加上索引。
2.count(字段)不会将,字段值为null,算到计数内,count(*)会算在内。
count()用法解释,count会把()内不为空Null的值计算在内,比如:
CREATE TABLE test (
`value` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO test (value) VALUES(1);
INSERT INTO test (value) VALUES(4);
INSERT INTO test (value) VALUES(5);
INSERT INTO test (value) VALUES(6);
INSERT INTO test (value) VALUES(4);
INSERT INTO test (value) VALUES(4);
INSERT INTO test (value) VALUES(5);
INSERT INTO test (value) VALUES(2);
INSERT INTO test (value) VALUES(8);
INSERT INTO test (value) VALUES(1);
SELECT COUNT(value=4) FROM test;结果为10,是错误的。
SELECT COUNT(value=4 OR NULL) FROM test;结果为3,是正确的。
因为当value不等于4的时候,括号内的结果为false,mysql看作是0,并非Null,所以仍然算在计数内。通过下面简单可知
SELECT 4=4, 3=4, 1 or null, 0 or null
结果为 1 | 0 | 1 | NULL
只有当value=4为false的时候,or null,括号内的值才为Null,才不会计算在内,得到正确答案。不然value等于任何值,答案都是10.
3.对limit进行优化,可以在不影响结果的情况下,对带有索引列进行排序,比如主键排序。
五.选择合适的列建立索引
1.在where从句,group by从句,order by 从句,on从句中出现的列建立索引。
2.索引字段越小越好,因为是分页进行存储的,字段越小,一页中索引会包含越多,一次IO操作获取的数据量就越大。
3.离散度大的列放到联合索引的前面。
例如,select count(distinct id),count(distinct real_name) from user;
id 是唯一值,所以离散度更高。而 real_name 会出现重复—>会有同名同姓的情况,所以离散度低。所以建立联合索引index(id,real_name)。
4.查找重复及冗余索引
select
a.TABLE_SCHEMA AS '数据名',
a.TABLE_NAME AS '表名',
a.INDEX_NAME AS '索引1',
b.INDEX_NAME AS '索引2',
a.COLUMN_NAME as '重复列名'
from STATISTICS a JOIN STATISTICS b ON
a.TABLE_SCHEMA = b.TABLE_SCHEMA
AND a.TABLE_NAME = b.TABLE_NAME
AND a.SEQ_IN_INDEX = b.SEQ_IN_INDEX
AND a.COLUMN_NAME = b.COLUMN_NAME
5.dt-duplicate-key-checker 索引检索分析工具。
pt-duplicate-key-checker -uroot -p'ROOT' -h 127.0.0.1
六.数据库结构的优化
选择合适的数据类型
1.使用可以存下你数据的最小数据类型
2.使用简单的数据类型,Int要比varchar类型在mysql的处理上简单
3.尽可能的使用not null定义字段
4.尽量少用text类型,非用不可时候最好考虑分表。
1、时间转时间戳:unix_timestamp("2016-08-01 13:14:00");
2、时间戳转时间:fromm_unixtime(1508076155)
3、INET_ATON()--ip地址转换成整型
4、INET_NTOA()--整型转换成ip地址
七.操作系统配置优化
数据库是基于操作系统的,目前大多数的MySQL都是安装在linux系统之上,
所以对于操作系统的一些参数配置也影响到MySQL的性能,下面就列出一些常用到
的系统配置。
网络方面的配置,要修改/etc/sysctl.conf文件
增加tcp支持的队列书
net.ipv4.tcp_max_syn_backlog=65535
减少断开连接时,资源的回收
net.ipv4.tcp_max_tw_buckets=8000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_fin_timeout=10
打开文件数的限制,可以使用ulimit -a 查看目录的各位闲置,可以修改
/etc/security/limits.conf文件,增加以下内容以修改打开文件数量的限制
*soft nofile 65535
*hard nofile 65535
除此之外最好在MySQL服务器上关闭iptables,selinux等防火墙软件。
八.mysql配置文件的优化
MySQL可以通过启动时指定配置参数和使用配置文件两种方法进行配置,在大多数情况下
配置文件位于/etc/my.cnf或/etc/mysql/my.cnf;在windows系统配置文件可以位于
C:/windows/my.ini文件,MySQL查找配置的顺序可以通过以下方法获得:
$:/usr/sbin/mysqld --verbose --help | grep -A 1 'Default options'
注意:如果存在多个位置存在配置文件,则后面的会覆盖前面的
常用参数说明
innodb_buffer_pool_size
非常重要的参数,用于配置innodb的缓冲池如果数据库中只有innodb表,
则推荐配置量为总内存的75%
下面是检测语句
select engine,round(sum(data_ength + index_length)/1024/1024,1) as 'Total MB',
from information_schema.tables where table_schema not in ('information_schema',
'performance_schema') group by engine;
innodb_buffer_pool_size >= Total MB
innodb_buffer_pool_instances
MySQL5.5中新增参数,可以控制缓冲池的个数,默认情况下只有一个
innodb_log_buffer_size
innodb log缓冲的大小,由于日志最长每秒钟就会刷新所以一般不用太大
innodb_flush_log_at_trx_commit
关键参数,对innodb的IO效率影响比较大,默认值为1,可以取0,1,2三个值,
一般建议设为2,但如果数据安全性要求比较高则使用默认值1.
innodb_read_io_threads
innodb_write_io_threads
以上两个参数决定了innodb读写IO进程数,默认4
innodb_file_per_table
关键参数,控制innodb中每一个表使用独立的表空间,默认为OFF,也就是所有表
都会建立在共享表空间。
innodb_stats_on_metadata
决定了MySQL在什么情况下会刷新innodb表的统计信息
mysql第三方配置工具:
https://tools.percona.com/wizard