mysql 优化详解

版权声明: https://blog.csdn.net/m0_37984616/article/details/81047676

MySQL体系架构

这里写图片描述
链接池组件、管理服务和工具组件、SQL接口组件、查询分析器组件、优化器组件、缓冲组件、插件式存储引擎、物理文件;
一、链接层:主要完成一些相似于链接处理,受权认证及相关的方案;
二、服务层:主要完成大多数核心服务功能;
三、引擎层:负责MySQL中数据的存储和提取,服务器经过API与存储引擎进行通讯;
注:储存引擎式基于表的,而不是数据库的;css

MySQL存储引擎

InnoDB 和 MyISAM区别:
一、InnoDB支持主外键、事务;
二、InnoDB是行锁,操做时候只锁一行数据,适合高并发;MyISAM是表索;
三、InnoDB不只缓存索引,还缓存真实数据;MyISAM只缓存索引;
四、InnoDB须要表空间大;
五、InnoDB关注事务,MyISAM关注性能(查);html

SQL优化

问:执行时间长,等待时间长
多是SQL语句太次,索引失效,关联查询太多join,服务器调优及参数设置(缓冲池)
SQL执行顺序:mysql

   
   
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
FROM <LEFT_TABLE> ON <JOIN_CONDITION> <JOIN_TYPR> JOIN <RIGHT_TABLE> WHERE GROUP BY HAVING SELECT DISTINCT ORDER BY

JOIN详解:
这里写图片描述
最后两个因为MySQL不支持FULL OUTER JOIN,因此用 UNION 链接,即1和2的语句进行UNION获得6,3和4的语句进行UNION获得7。web

索引

索引:排好序的快速查找数据结构;
优势:提升数据检索的效率,下降数据排序的成本;
缺点:会下降更新表的速度;算法

单值索引:一个索引只包含单个列,一个表能够由多个单值索引;
惟一索引:索引列的值必须惟一,容许有空值;
复合索引:即一个索引包含多个列;sql

   
   
   
   
  • 1
  • 2
CREATE [UNIQUE] INDEX indexname ON tablename(columnname(length)); ALTER table tablename ADD [UNIQUE] INDEX indexname (columnname(length));

索引结构:
BTree索引,Hash索引,full-text全文索引,R-Tree索引;数据库

B+树与B树的不一样在于:
(1)全部关键字存储在叶子节点,非叶子节点不存储真正的data
(2)为全部叶子节点增长了一个链指针缓存

下图是BTree索引数据结构
这里写图片描述服务器

索引性能分析:
Explain(执行计划):
使用:EXPLAIN + sql语句;
做用:
一、表的读取顺序;
二、数据读取操做的操做类型;
三、哪些索引可使用;
四、那些索引被实际使用;
五、表之间的引用;
六、每张表有多少行被优化器查询;
这里写图片描述
id
select 查询的序列号,包含一组数字,表示查询中执行select子句或操做表的顺序;
有三种状况:
   一、id相同,执行顺序由上至下;
   二、id不一样,若是是子查询,id的序号会递增,id值越大优先级越高,先被执行 ;
   三、id有相同,有不一样,相同的能够认为是一组,从上往下顺序执行;在全部组中,id值越大,优先级越高,先被执行;(table 列中的 derived 的意思是衍生,由 id 衍生的)markdown

select_type
这里写图片描述

table
显示这一行数据是哪一个表的;

type
性能高低从上到下的顺序;
这里写图片描述

possible_keys
显示可能应用在这张表中的索引,能够是多个;
查询涉及到的字段上若存在索引,则被列出,但不必定被使用;

key
实际使用到的索引,null表明没使用索引。
查询若使用覆盖索引,则该索引仅出如今key列表中;

key_len
表示索引中使用的字节数,越小越好,显示的值为索引字段的最大可能长度,并不是实际使用长度。

ref
显示索引的哪一列被使用了,最好是常量;

rows
根据表统计信息及索引选用状况,大体估计出找到所需的记录所须要读取的行数;

extra
包含不适合在其余列展现的但重要的额外信息
这里写图片描述
usingwhere 使用where语句;
usingbuffer 使用缓冲池;

若是查询的两个表大小至关,那么用in和exists差异不大。
若是两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:
因此不管那个表大,用not exists都比not in要快。not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。

Join链接索引分析
单表分析
例:select id from A where c1 = 1 and c2 > 1 order by v1 desc limit 1;
创建联合索引(c1,c2,v1),但explain时候发现 type 是range,extra中使用using filesort,这须要优化;
产生缘由:按照BTree索引工做原理,先排序c1,若是c1相同,排序c2,c2相同在排序v1,当c2字段在联合索引中处于中间位置,由于c2 > 1条件是一个范围值(range),MySQL没法利用索引在对后面的v1部分进行索引。因此创建(c1,v1)解决这个问题。

双表分析
左链接加在右表的索引,右链接加在左表的索引;
Left Join 条件用于肯定如何从右表搜索行,左边数据必定有,因此右边数据必定要建索引。

三表分析
建索引和双表的原理相同;

总结
尽量减小Join语句的NestedLoop的循环总次数,永远用小结果集驱动大的结果集;
优先优化NestedLoop的内层循环;
保证Join语句中被驱动表上Join条件字段已经被索引;

索引失效

一、最好全值匹配;
二、最左前缀法则:若是索引了多列,查询从索引的最左前列开始,且不能跳过索引中的列;
三、不在索引列上作任何操做(计算,函数,类型转换),会致使索引时校而转向全表扫描;
四、存储引擎不能使用索引中范围条件右边的列,即范围以后全失效;
五、尽可能使用覆盖索引,只访问索引的查询(索引列和查询列一致),减小selec *;
六、MySQL在使用不等于的时候没法使用索引会致使全表扫描;
七、is null,is not null 也没法使用索引;
八、like 以通配符开头(’%aa‘)索引会失效,变成全表扫描;
九、字符串不加单引号,索引失效;
十、少用 or,用它来链接时候会索引失效

覆盖索引:建索引的列和要查询的列相同,例如索引列是c1,c2,select 查询的也是c1,c2;
定值是常量,范围以后必失效,最终看排序,通常order by 是给个范围;
group by 分组,分组以前必排序,顺序不对会有临时表产生;

永远小表驱动大表
in 和 exists 选择:

   
   
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
// 工做原理,先查B表数据,而后查A的 id select * from A where id in (select id from B) // 工做原理,先查A表的id,而后查B表的id select * from A a where exists (select 1 from B b where a.id = b.id ) // 结论:当B表的数据小于A表时候用 in;当A表数据小时候用 exists

Order By 排序
MySQL支持两种排序,index和fileSort,index效率高,它指MySQL扫描索引自己完成排序。
Order By知足两种状况使用index:
一、Order By 语句使用索引最左前列
二、使用where子句与Order By子句条件组合知足索引最左前列
若是不在索引列上,fileSort有两种算法,4.1版本以前双路排序,进行两次IO;以后单路排序,进行一次IO;
Order By时不要select *,只查询所须要的字段;当两种算法的数据超出sort_buffer的容量会建立tmp文件进行合并运算,致使屡次IO,因此须要尝试提升sort_buffer_size 和
max_length_for_sort_ size。

为排序使用索引,MySQL能为排序与查询使用相同的索引

查询截取分析

一、观察,查看慢SQL状况;
二、开启查询日志,设置阀值;
三、explain 分析;
四、show profile 查看执行细节和生命周期状况
五、dba 进行参数调优

慢查询日志
响应时间超过long_query_tine的SQL,被记录到慢查询日志中。

   
   
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
// SHOW VARIABLES LIKE '%slow_query_log%' ; 查看是否开启,默认没开启 // set global slow_quary_log = 1; 开启,仅本数据库有效,重启MySQL以后失效。 // show variables like '%long_query_time%'; 查看当前多少秒算慢 // set global long_query_time = 3; 设置慢的阙值时间 // show global status like '%Slow_queries%'; 查看当前数据库有多少条慢SQL

Show Profile
是MySQL提供能够用来分析当前会话中语句执行的资源状况,能够用于SQL的调优的测量。
默认关闭,并保存最近15次结果;

   
   
   
   
  • 1
  • 2
  • 3
// set profiling = on ; 开启 // show profiles; 查看执行过的sql // SHOW PROFILE cpu,block io FOR QUERY 87; 查看这个执行sql 的生命周期相关信息。

converting HEAP to MyISAM 查询结果太大,内存不够用了往磁盘上搬;
Creating tmp table 建立临时表,拷贝数据到临时表,用完再删除;
Copying to tmp table on disk 把内存中临时表复制到磁盘,危险!
locked

全局查询日志
不能够在生产环境中开启这个功能。

   
   
   
   
  • 1
  • 2
  • 3
// set global general_log = 1; // set global log_output = 'TABLE'; // 此后,你全部编写的sql语句都会记录到mysql库中的general_log表;

MySQL锁机制

分类能够分为读锁(共享锁)和写锁;表锁和行锁;

表锁:偏向MyISAM存储引擎,开销小,加锁快,并发度低;
加锁:lock table tablename read,tablename2 write;解锁:unlock tables;
查看哪些表被锁了 show open tables;
加读锁
这里写图片描述
加写锁
这里写图片描述
MyISAM在执行查询语句前,会自动给涉及的全部表加读锁,在执行增删改前,会自动给涉及的表加写锁。
一、对MyISAM表的操做(加读锁),不会阻塞其余进程对同一表的读请求,但会阻塞对同一表的写请求,只有当读锁释放后,才会执行其余进程的写操做。
二、对MyISAM表的操做(加写锁),会阻塞其余进程对同一表的读和写操做,只有当写锁释放后,才会执行其余进程的读写操做。

分析表锁定
show status likes ‘table%’;
Table_locks_immediate:产生表级锁定的次数;
Table_locks_waited:出现表级锁定争用而发生等待的次数,不能当即获取锁的次数,每等待一次锁值加1;
MyISAM的读写锁调度是写优先,因此不适合作写为主表的引擎。

行锁:偏向InnoDB存储引擎,开销大,会出现死锁,锁的粒度最小,发生锁冲突的几率最低,并发度高。
InnoDB与MyISAM最大不一样是InnoDB支持事务,而且采用行级锁;
这里写图片描述
事务隔离级别:未提交读,已提交读,可重复度,可序列化。MySQL默认是可重复读。
无索引,行锁变表锁

当咱们使用范围条件而不是相等条件检索数据,并请求共享排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但不存在的记录,叫作间隙;InnoDB也会对这个间隙加锁。
这里写图片描述

主从复制

复制的基本原理
slave会从master读取binlog来进行数据同步。
MySQL复制过程分为三步:
一、master将改变记录到二进制日志(binary log);
二、slave将master的binary log events 拷贝到它的中继日志(relay log);
三、slave重作中继日志的时间,将改变应用到本身的数据库中,MySQL复制是异步的且串行化;
每一个slave只有一个master,只能有一个惟一的服务器ID,每一个master能够有多个salve;

DML
DML(data manipulation language)数据操纵语言,好比SELECT、UPDATE、INSERT、DELETE;
DDL
DDL(data definition language)数据库定义语言,CREATE、ALTER、DROP等;
DCL
DCL(Data Control Language)数据库控制语言,grant,deny,revoke等;

MyISAM使用B-Tree实现主键索引、惟一索引和非主键索引。
InnoDB中非主键索引使用的是B-Tree数据结构,而主键索引使用的是B+Tree。

二级索引
mysql中每一个表都有一个聚簇索引(clustered index ),除此以外的表上的每一个非聚簇索引都是二级索引,又叫辅助索引(secondary indexes)。

以InnoDB来讲,每一个InnoDB表具备一个特殊的索引称为汇集索引。若是您的表上定义有主键,该主键索引是汇集索引。若是你不定义为您的表的主键时,MySQL取第一个惟一索引(unique)并且只含非空列(NOT NULL)做为主键,InnoDB使用它做为汇集索引。若是没有这样的列,InnoDB就本身产生一个这样的ID值,它有六个字节,并且是隐藏的,使其做为聚簇索引。

相关文章
相关标签/搜索