- 目的
避免出现页面访问错误
慢查询造成页面无法加载
阻塞造成数据无法提交
优化从sql及索引,数据库结构,系统配置,硬件 - 日志
慢查询日志:
show variables like 'slow_query_log' set global slow_query_log_file='日志地址';
set global slow_query_log=on;
set global log_queries_not_using_indexes=on;//未使用索引 set global long_query_time=1
show variables like 'slow_query_log%';#查询慢日志状态是否开启k
show variables like 'long_query_time';#显示多久时间要被记录
show global variables like 'long_query_time';#
set GLOBAL long_query_time = 1;#设置时间为1秒
set GLOBAL SLOW_QUERY_LOG = 1;#开启慢查询日志
set GLOBAL LOG_QUERIES_NOT_USING_INDEXES = 1;#开启记录查询中不带索引的 - 日志分析
mysql自带的工具:mysqldumpslow
pt输出到文件:pt-query-digest slow-log > slow_log.report
pt输出到数据库:pt_query-digest slow.log -review \h=127.1,D=test,p=root,P=3306,u=root,t=query_review --create-reviewtable --review-history t= hostname_slow - 通过日志查找到问题
1.查询次数多且每次查询占用时间长的sql:pt-query-digest分析的前几个查询
2.I/O大的sql:注意pt-query-digest分析中的Rows examine项
3.未命中索引的sql:注意pt-query-digest分析中Rows examine和Rows send的对比。 - 分析具体sql
explain 返回各列含义:
talbe:数据表
type: 显示连接使用何种类型,从最好到差:const,eq_reg,ref,reange,index,all
possible_keys:显示可能应用到这张表的索引,为空是没有可能索引
key:实际用到的索引,为null则没有使用索引
key_len:使用的索引的长度,在不损失精确性情况下,长度越短越好
ref:显示索引的哪一列被使用,如果可能的话,是一个常数
rows:msyql认为必须检查的用来返回请求数据的行数
extra:Using filesort:看到这个查询就需要优化了,mysql需要进行额外的步骤来发现如何对返回的行排序,它根据连接类型及存储排序键值和匹配条件的全部行的行指针来排序全部行。
Using temporary:这个也需要优化了,mysql需要创建一个临时表来存储结果,这通常发生在对不同的列集进行order by 上,而不是group by 上。
- 具体例子
count():count(*)含null的列,count(列)不含null的列
max(列):一般通过建立对列的索引来优化
子查询的优化:通常把子查询优化成join查询,优化时要注意关联建是否有一对多的关系,要注意重复数据(使用distinct)。
group by 优化:两个表关联查询优化成子查询方式
limit优化:常用于分页处理,时常会伴随order by 从句使用,因此大多时候会使用filesorts这样会造成大量的io问题。优化步骤1,使用有索引的列或主键进行order by 操作,2.记录上次返回的主键,在下次查询时使用主键过滤,避免过多扫描表。 - 索引优化:
where,group by ,order by ,on 从句中出现的列建立索引,索引字段越小越好,离散度大的列放到联合索引的前面(离散度是指重复率)。
索引查询快,但插入更改慢
- 查找重复索引
使用
use information_schema;
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.TBLE_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 WHERE a.SEQ_IN_INDEX=1 AND a.INDEX_NAME<>b.INDEX_NAME使用工具,pt_duplicate-key-checker
pt-duplicate-key-checker -uroot -p '' -h 127.0.0.1
分析不用的索引,配合慢查询日志
pt-index-usage -uroot -p'pwd' mysql-slow.log
- 数据库结构优化:
数据类型:使用可以存下你的数据的最小的数据类型,使用简单的数据类型,Int比varchar在处理上要简单,尽可能的使用not null定义字段,少用text类型,非用可考虑分表。
使用int来存储日期,利用FROM_UNIXTIME(),UNIX_TIMESTAMP()两个函数来转化。
使用bigint存ip地址,利用INET_ATON(),INET_NTOA()两个函数来转换。 - 范式优化与返范式优化
第三范式:不存在非关键字对任意候选关键字段的传递函数依赖。 - 表的垂直拆分
原则:不常用的字段放在一个表中,大字段放到一个表中,经常使用的字段放在一起 - 表的水平拆分
- 系统优化
操作系统配置优化:网络方面的配置,要修改/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配置文件优化
mysql通过启动时指定配置参数和使用配置文件两种方法进行配置,mysql查找配置文件的顺序可以通过:$/usr/sbin/mysqlId --verbose --help | grep -A 1'Default options'
innodb_buffer_pool_size非常重要的一个参数,用于配置Innodb的缓冲池,如果数据库中只有Innodb表,则推荐配置量为总内存的75%
SELECT ENGINE,ROUND(SUM(data_length+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 MBinnodb_buffer_pool_instances 可以控制缓冲池的个数,默认情况下只有一份。
innodb_log_buffer_size 缓冲的大小,由于日志最长每秒就会刷新,所以不用太大
innodb_flush_log_at_trx_commit 关键参数,对innodb的IO效率影响很大,默认值为1,一般建议设为2。如果数据安全性要求高就用1.
innodb_read_io_threads\innodb_write_io_threads 两个参数决定读写的io进程数,默认为4
innodb_file_per_table 关键参数,控制Innodb每一个表使用独立的表空间,默认为off,也就是所有表会建立在共享表空间中,表空间不会自动收缩,建立设为on。
innodb_stats_on_metadata 决定什么情况下会刷新innodb表的统计信息,建议设为off - 第三方工具配置