Mysql优化、调优详解

有用麻烦点个赞哦

1、mysql优化分析流程

1、慢查询的开启并捕获运行一段时间(至少一天),查看生产慢sql的情况,开启慢查询日志,设置阈值,例如超过5秒就是慢日志,抓去出来分析
2、explain + 慢sql进行分析(基本完成大多分析)
3、show profile(更猛)查询sql在mysql服务器里面执行的细节和声明周期
4、SQL数据库服务器的参数调优(DBA或运维)


2、索引优化分析

2.1、关于索引

简单了解:排好序的快速查找的数据结构除数据本身以外数据库还维护着满足特定查找算法的数据结构,实现查找算法。但一般来说索引本身也很大,不可能全部储存在内存中。因此索引往往以索引文件的形式储存在磁盘上默认索引都是指B树其中聚集、次要、覆盖、全文、符合、前缀、唯一索引都是默认使用B+树,除了B+树以外还有哈希索引。
索引失效:频繁改动的数据不适合作为索引,每次更新要重新改索引索引优势提高检索效率降低io成本通过索引列进行排序,降低排序的成本,降低cpu的消耗劣势占用空间降低更新表的速度
索引分类:单列索引 一个索引只包含单个列,一个表可以有多个单列索引唯一索引 索引列必须唯一但是允许空值

2.2、性能分析

mysql常见瓶颈 cpu在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候。
1. IO:磁盘I/O瓶颈发生在装入数据远大于内存容量的时候
2. 服务器硬件的性能瓶颈:top,free,iostat和vmstat来查看系统性能状态

MySql Query Optimizer mysql自带的分析器
Explain进行分析 :下面重点讲解

2.3、Explain的使用

2.3.1 作用:

对sql语句进行优化使用方法:explain + sql语句,根据显示的表进行优化

2.3.2通过Explain了解系信息:

1、表的读取顺序
2、数据读取操作的操作类型
3、哪些索引可以被使用
4、哪些索引实际被使用
5、表之间的引用
6、每张表有多少行被优化器查询 返回字段解释id 表示查询中执行select子句或操作表的顺序

2.3.3 Explain 表字段(部分)

id id相同视为同一组从上往下执行、所有组中id越大优先级越高,越先执行
select_type 查询类型simple primary(任何复杂查询,外层的嵌套查询 )
union,union Result 从union表获取结果的select
possible_keys 指出 mysql 在查询中可能会使用的索引,但不一定会使用,mysql 会根据统计信息选出代价最小的索引
key 真实使用的索引
ref r用来与 key 中所选索引列比较的常量 (const) 或者连接查询列(显示为该列名字)
rows 找到所需的纪录需要扫描多少行
extra mysql 认为很关键,但是又不应该出现在前面所述字段的信息


2.3.4 根据Explain进行索引sql优化

1、全值匹配
索引为(a,b,c),匹配条件:where a=1 and b=2 and c=3 此时效率最佳,完美匹配索引
2、最佳左前缀法则
如果索引了多列,要遵守最左前缀法则,指的是查询从索引的最左前列开始并且不跳过中间的索引列
3、不在索引上做任何操作
计算,函数,(自动、手动)类型转换,会导致索引失效
4、产生全局扫描存储引擎不能使用索引范围条件的右边的列建
例子:三级索引(a,b,c)时,select where a(= 什么) and b > 什么 order by c会导致索引失效 因为b是一个范围值,优化:建立索引为(a,c)尽量使用覆盖索引,减少用select *
5、MySQL在不使用不等于时无法使用索引
a != b 以及 a <> b 都会
6、is null,is not null 无法使用索引
创建表时,空值最好设定一个默认值,避免出现索引失效)
7、like以通配符开头会使索引失效
(%abc这个会)(abc%这个不会),mysql索引失效会变成全表扫描的操作,
面试问题:
如何结局like"%字符串%"时索引不被使用时,用覆盖索引解决:比如查的字段为id,name(或者两者其一),可以以(id,name)为组合索引,产生覆盖索引,此时Key字段为该组合索引,表明索引并没有失效
8、字符串不加单引号索引失效
如varchar类型 不加单引号,(where id=‘1’)写成了(where id = 1),产生了隐含的类型转换
9、少用or
用它连接时索引失效面试要点索引为(a,b,c,d)的复合索引

2.3.5关于索引进行实例分析

1、查询时where a = 1and b = 2 and c =3 and d =4 与where d = 4and b = 2 and c =3 and a =1 逻辑相同(Mysql 会自己调整成前者)
2、查询时where a = 1and b = 2 and c >3 and d =4 与where a = 1and b = 2 and d>4 and c =3 不同(因为索引顺序为abcd,所以Mysql 会自己调整为where a = 1and b = 2 and c =3 and d>4)索引长度不同,但索引类型同样为range
3、where a = 1and b = 2 and d =4 order by c ;用到了ab查找,c排序explain 返回 ref为2 ,不会把c统计进去
4、where a = 1and b = 2 order by c ;情况与3一样,不会因为d的是否使用而改变(因为范围查找右边无法使用索引)
5、 where a = 1and b = 2 order by d;extra 产生 filesoft,因为第三索引的c没了,ref为2(使用了ab索引查找)
6、where a=1 and e=5 order by b,c; ref为const,(bc用于排序所以不会有filesoft)
7、where a=1 and e=5 order by c,b;ref为const,但会产生using filesoft,orderby的 顺序颠倒了;
8、where a=1 and b =2 order by b,c;ref为const,const。(ab)
9、where a=1 and b =2 and e=5 order by b,c; ref为const,const。(ab)
10、where a=1 and b =2 and e=5 order by c,b;其实和8一样,ref为const,const。(ab) 因为索引b已用于查找,所以order中的c可以直接使用,顺序颠倒不影响;
11、where a=1 and d=4 group by b,c;ref 为const 只调用了a查找
12、where a=1 and d=4 group by c,b;ref 为const 只调用了a查找,并且出现了using filesort和using temporary(group by 分组之前必定要排序,如果顺序错乱,会产生临时表)
13、where a=1 and b like"%字符串" and c=3; ref为 const,索引用到了a
14、where a=1 and b like"字符串%" and c=3;ref为 const,const,const。索引用到了abc
15、where a=1 and b like"%字符串%" and c=3;ref为 const,索引用到了a
16、where a=1 and b like"字符串%字符串%" and c=3;ref为 const,const,const。索引用到了abc

2.3.6索引建议:

1、单键索引,尽量选择针对当前query过滤性更好的索引
2、组合索引时,query过滤性更好的字段在索引字段的左边
3、组合索引时尽量选择可以包含当且query中的where字句中更多的字段
4、尽可能通过分析统计信息和调整query的写法来达到选择适合索引的目的

3、查询截取分析

3.1查询优化

小表驱动大表
mysql 都是使用(Nested Loop )循环套嵌的方式实现 join,耗时间比较多的是数据库的链接与释放。
以for循环为例
for(i=0;i<1000;i++){ for(j =0 ; j<5;j++ )}
远不如
for(i=0;i<5;i++){ for(j =0 ; j<1000;j++ )}
应用
exists和in不同,小表驱动大表原则
exists 理解为主查询的句子放到子查询中做验证,只返回true 和false。
select * from A where id in (select id in B)等价于

for select id from B    
	for select * from A where A.id =B.id

B表数据小于A表用in
select * from A where id exists(select 1 from B where in B.id = A.id)等价于

 for select id from A    
	for select * from A where A.id =B.id

B表数据大于A表用exists


3.2 双路排序和单路排序

3.2.1 简介

I/O是相当耗时的,Mysql 4.1版本以前使用双路排序。两次扫描磁盘1、先扫描并排序再扫描搜索需要的内容。4.1后单路排序orderby 在sort_buffer对数据进行排序,然后用列表进行输出,效率更快,随机IO变成顺序IO。但是牺牲了更多的空间,每一行数据都保存在内存单路排序。

3.2.2单路排序存在问题

如果取出的数据总体大小超出了sort_buffer的容量,导致每次只能去sort_buffer的容量大小的数据,进行排序,从而多次I/O得不偿失。
解决:提高OrderBy速度:
1、不用select *。只有字段大小总和小于max_length_for_sort_data且字段不是TEXT|BLOB类型时,会用改进后的算法单路排序,否则还是会用双路服务器参数调优
2、增大sort_buffer_size参数的设置
3、增大max_length_for_sort_data的参数设置,但过高会使数据总容量超过sort_buffer_size的概率增大。为排序使用索引

3.2.3其他

1、mysql两种排序方式:文件排序或扫描有序索引排序
2、mysql能为排序和查询使用相同索引order by 要么一起升序要么一起降序group by其实与order by差不多,只多了一个having(能使用where的就不使用having)

3.3慢查询日志

3.3.1定义

慢查询日志设定一个阈值long_query_time,sql具体运行时间超过(=不算在内)这个阈值就会被记录到慢查询日志中 默认情况下mysql没有开启慢查询,除非调优需要一般不建议启动,会降低性能。

3.3.2 启动方式

1、临时单个数据库启动(mysql重启后会失效)set 数据库名 slow_query_log=1set 数据库名 long_query_time=时间阈值重开窗口即可;
2、永久启动修改my.cnf配置文件slow_query_log=1slow_query_log_file=储存到的文件名(不指定也会默认配置)long_query_time=时间阈值long_output=FILE重开窗口即可

3.3.3 日志分析工具mysqldumpslow

用法
手动分析日志是效率太低引出mysqldumpslow可以查询前几条数据着重分析日志分析工具
参数表:-help 查看帮助-s 排序方式 c 访问次数 l 锁定时间 r 返回记录 t 查询时间 al 平均锁定时间 ar 平均返回记录 at 平均查询时间-t 即返回前面多少条的数据-g 后面搭配正则表达式,大小写不敏感 。

3.4 Show Profiles

介绍
mysql用于分析当前会话中语句执行的资源消耗情况,可以用于sql的调优测量,默认保存最近的15次运行结果
使用
1、show profiles;查看运行时间和sql语句
2、show profile cpu,block_io(这两个参数相对常用) for query 想要查看的sql id号(上一条语句显示的表里有)
如何判断返回的数据存在的问题?
1、converting HEAP to MyISAM 查询结果太大,内存不够用了
2、Creating tem table创建临时表
3、Copying to tmp table on disk 把内存中的临时表复制到内存
4、locked

3.5 全局查询日志

只允许在测试环境用,比较推荐功能更为抢答的show profile;

有用麻烦点个赞哦

发布了23 篇原创文章 · 获赞 24 · 访问量 3061

猜你喜欢

转载自blog.csdn.net/weixin_44303896/article/details/104173195