目录
第一章、mysql框架
一、mysql配置文件
二、mysql的逻辑框架介绍
1、总体概述
2、详情说明
3、存储引擎
第二章:索引优化分析
一、性能下降SQL慢,执行时间长,等待时间长原因
二、SQL执行加载顺序
1、手写的SQL
2、机读
3、总结
第三章、七种join理论
第四章、索引简介
一、索引是什么
二、索引优势和劣势
1、优势
2、劣势
三、索引分类和建立索引命令语句
1、索引分类
2、基本语法
四、索引结构与检索原理
(1)结构
(2)检索原理
五、那些情况适合建索引,那些情况不适合建索引
(1)需要
(2)不需要
第五章、性能分析前提知识
1、MySQL Query Optimizer
2、mysql常见瓶颈
第六章、explain
(一)简介
(二)能干嘛
(三)怎么玩
(四)explain之id介绍
(五)explain之select_type介绍
(六)explain之table介绍
(七)explain之type介绍
(八)explain值possible_keys和key介绍
(九)explain值key_len介绍
(十)explain之ref介绍
(十一)explain之rows介绍
(十二)explain值extra介绍
1、Using filesort 久死一生
2、Using temorary 十死无生
3.Using index 不错
4、Using where
5、using join buffer
6、impossible where
7、select tables optimized away
8、distinct
1、二进制日志log-bin
主从复制用
2、错误日志log-error
默认是关闭的,记录严重的警告和错误信息,每次启动和关闭的详细信息等。
3、查询日志log
默认关闭,记录查询sql语句,如果开启回降低mysql的整体性能,因为记录日志也是需要消耗系统资源的
4、数据文件
(1)window mysql\data 目录下可以挑选很多库
linux 默认路径: /var/lib/mysql
(2)frm文件:存放表结构
(3)myd文件:存放表数据
(4)myi文件:存放表索引
(5)如何配置
和其他数据库相比,MySQL有点与众不同,他的架构可以在多种不同场景中应用并发挥良好作用,主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其他系统任务一级数据的存储提取相分离。这种架构可以根据业务的需求和实际需求选择合适的存储引擎
1)、连接层
最上层是一些客户端和连接服务,包含本地sock通信和大多数基于客户端/服务端工具实现的类似tcp/ip的通信,主要是完成一些类似于连接处理、授权认证、及相关的安全方案、在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程、同样在该层上可以实现基于SSL的安全链接,服务器也会为安全接入的每个客户端验证它所具有的操作权限
2)、服务层
第二层架构主要是完成大多数的核心服务功能,如SQL接口,并完成缓存的查询,SQL的分析和优化及部分内置函数的执行,所有跨存储引擎的功能也在这一层实现,如过程,函数等。在该层,服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化,如确定查询标的顺序,是否利用索引等,最后生成相应的执行操作。如果是select语句,服务器还会查询内部的缓存。如果缓存空间足够大,这样在解决大量读操作的环境中,能够很好地提升系统的性能
3)、引擎层
存储引擎层,存储引擎真正的负责了MySQL中数据的存储和提取,服务器通过API与存储引擎进行通信,不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需求进行选取。主要有MyISAM 和 InnoDB
4)、存储层
数据存储层,主要是将数据存储在运行于裸设备的文件系统上,并完成与存储引擎的交互。
(1)命令
a、show engines
b、show variables like '%storage_engine%';
(2)俩引擎对比
注意:FULL OUTER JOIN mysql不支持这种语法
第六种:
select * from tbl_empl a left join tbl_dept b on a.deptId=b.id union select * from tbl_emp a right join tbl_dept b on a.deptId=b.id;
第七种:
select * from tbl_emp a left join tbl_dept b on a.deptId = b.Id where b.id is null union select * from tbl_emp a right join tbl_dept b on a.deptId = b.id where a.deptId is null;
MYSQL官方对索引的定义为:索引是帮助MySQL高效获取数据的数据结构————可以简单理解为“排好序的快速查找数据结构”
可以得到索引的本质:索引是数据结构
在数据之外,数据库系统还维护着特定查找算法的数据结构,这些数据结构以某种方式引用(指定)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。下图就是一种可能的索引方式实例:
为了加快Col2的查找,可以维护一个右边所示的二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在一定的复杂度内获取到相应数据,从而快速的检索出符合条件的记录。
表删数据 索引要重建
一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上
我们平常说的索引,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉的)结构组织的索引。其中聚集索引,次要索引,符合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种类型的索引之外,还有哈希索引等
建立索引,提高数据索引的效率,降低数据库的IO成本
通过索引对数据进行排序,降低数据排序的成本,降低了CPU的消耗
实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占空间的
虽然索引打打提高了查询速度,同事却会降低更新表的速度,入队表进行INSERT UPDATE 和DELETE,因为更新表示,MySQL不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息。
索引知识提高效率的一个因素,如果你的MySQL有大数据的表,就需要花时间研究建立最优秀的索引或优化查询语句
(1)创建
CREATE [UNIQUE] INDEX indexName ON mytable(columnname(length));
ALERT mytable ADD [UNIQUE] INDEX [indexName] ON (columname(length))
(2)删除
DROP INDEX [indexName] ON mytable;
SHOW INDEX FROM table_name\G
(3)使用ALTER命令
有四种方式来添加数据库表的索引
BTree索引、Hash索引、full-text索引、R-Tree索引
【初始化介绍】
一颗B+树,浅蓝色的块我们称之为一个磁盘块,可以看出每个磁盘块包含几个数据项(深蓝色所示)和指针(黄色所示),如磁盘块1包含数据项17和35,包含指针P1.P2.P3
P1表示小于17的磁盘块,P2表示在17和35之间的磁盘块,P3表示大于35的磁盘块。
真实的数据存在于叶子节点即:3、5、9、10、13、15、28、29、36、60、75、79、90、99.
非叶子节点只不存储真实的数据,只存储指引索引方向的数据项,如17、35并不真实存在于数据库表中。
【查找过程】
如果要查找数据项29,那么首先会把磁盘块1由磁盘加载到内存,此时发生一次IO,在内存中用二分查找确定29在17和35之间,锁定磁盘块1的P2指针,内存时间因为非常短(相比磁盘的IO)可以忽略不计,通过磁盘1的P2指针的磁盘地址把磁盘块3由磁盘加载到内存,发生第二次IO,29在26和30之间,锁定磁盘块3的P2指针,通过指针加载磁盘块8到内存,发生第三次IO,同事内存中做二分查找找到29,结束查询,总计三次IO。
真实的情况是,3层的b+树可以表示上百万的数据,如果上百万的数据查找只需要三次IO,性能提高将是巨大的,如果没有索引,每个数据项都要发生一次IO,那么总共需要百万次的IO,显然成本非常非常高。
(1)Mysql中有负责优化SELECT语句的优化器模块,主要功能:通过计算分析系统中收集到的统计信息,为客户端请求的Query提供他认为最优的执行计划(他认为最优的数据索引方式,但不见得是DBA认为是最优的,这部分最消耗时间)
(2)当客户端向MySQL请求一条Query,命令解析器模块完成请求分类,区别出示SELECT并转发给MySQL Query Optimizer时,MySQL Query Optimizer首先会对整条query进行优化,处理掉一些常量表达式的预算,直接转换算成常量值,并对Query中的查询条件进行简化和转换,如去掉一些无用或显而易见的条件,结构调整等,然后分析Query中的Hint信息(如果有),看现实Hint信息是否可以万却确定failQuery的执行计划。如果没有Hint或Hint信息还不足以完全确定执行计划,则会读取所涉及对象的统计信息,根据Query进行写相应的计算分析,然后在得出最后的执行计划
使用explain关键字可以模拟执行sql查询语句,从而知道mysql是如何处理你的sql语句的,分析你的查询语句或者是表结构的性能瓶颈
1、explain + SQL语句
2、执行计划包换的信息
1、select 查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序
2、三种情况
(1)id相同,执行顺序由上至下
先加载t1,再加载t3,最后加载t2
(2)id不同,如果是子查询,id的序号回递增,id值越大优先级越高,越先被执行
(3)id相同不同
SIMPLE:简单的select查询,查询中不包含子查询或者UNION
PRIMARY:查询中若包含任何复杂的字部分,最外层查询则被标记
SUBQUERY:在select或where列表中包含了子查询
DERIVED:在from列表中包含的子查询被表姐为DERIVED(衍生),mysql回递归执行这些子查询,把结果放在临时表中
UNION:若第二个SELECT出现在UNION之后,则被标记为UNION;若UNION包含在FROM子句的子查询中,外层SELECT将被表姐为DERIVED
UNION RESULT
显示这一行的数据是关于哪张表的
1、type代表查询用了何种类型
2、类型排序(从最好到最坏依次是)
system>const>eq_ref>ref>range>index>ALL
一般来说,得保证至少达到range级别,最好能达到ref
3、type的详解
①、system
表中有一行数据(等于系统表),这是const类型的特例,平时不会出现,这个可以忽略不计
②、const
表示通过索引一次就能找到了,const用于比较primary key或者unique索引。因为只匹配一行数据,所以很快,如将主键置于where列表中,mysql就能将该查询转换成一个常量
③、eq_ref
唯一性索引扫描,对于每个索引建,表中只有一条记录与之匹配,常见于主键或者唯一索引扫描
④、ref
非唯一性索引扫描,返回匹配摸个单独值得所有行
本质上也是一种索引访问,他返回所有匹配摸个单独值的行,然而,他可能会找到多个符合条件的行,多以该属于查找和扫描的混合体
(上面截图,为t1表的两个字段col1,col2创建了一个索引,然后查询t1表col1字段的count最后进行一个查询)
⑤、range
只索引给定范围的行,使用一个索引来选择行,key列显示使用了哪个索引
一般就是在你的where语句中出现了between、<、>、in等的查询
这种范围扫描索引比全表扫描要好,因为他只需要开始于索引的某一点,而结束于另一点,不用去扫描全部索引
⑥、index
Full Index Scan,index和All区别为indx类型只遍历索引树。这通常比All快,因为索引文件通常比数据文件快
(也就是说虽然all和index都是读全表,但index是从索引中读取,而all是从硬盘中读取)
⑦、all
full table scan,将遍历全表以找到匹配的行
注释:一般来说保证查询至少达到range基本,最好能达到ref级别
possible_keys理论上可能用到的索引
key实际用到的索引(查询中若使用覆盖索引,则该索引仅出现在可以列表中)
覆盖索引:select后面接的字段(下面为col1,col2)和创建的符合索引的个数和顺序一模一样
理论上,应该用不到索引,实际上,select的列刚好和符合索引一样,就扫描了(可以为ind_col1_col2)
表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度,在不损失精确性的情况下,长度越短越好
key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出来的
ref:显示索引的哪一类被使用了,如果可能的话,是一个常数。哪些类或者常量用于查询索引列上的值。
根据表统计信息及索引选用情况,大致估算出所需的记录所需要读取的行数
包含不适合在其他列中显示但十分重要的额外信息
说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引书序进行排序
MySQL中无法利用索引完成的排序操作成为“文件排序”
eg:下图索引建立的规则是col1,col2,col3因此查询用到了索引,但是排序的时候用不到索引了
查询中排序的字段,排序字段若通过索引去访问将大大提高排序速度
用不上索引,还产生了临时表,常见于排序order by 和分组查询group by
表示相应的select操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错
如果同时出现using where ,表明索引被用来执行索引键值的查找
如果没有同时出现using where,表明索引用来读取数据而非执行查找动作
覆盖索引
理解一:就是select的数据列只用从索引中就能够取得,不必读取数据行,MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件,换句话说查询列要被所建的索引覆盖
理解二:索引是高效找到行的一个方法,但是一般数据库也能使用索引找到一个列的数据,因此他不必读取整个行,毕竟索引叶子节点存储了它们索引的数据;当能通过读取索引就可以得到想要的数据,那就不需要读取行了,一个索引包含了(或覆盖了)满足查询结果的数据就叫做覆盖索引
注意:如果要使用覆盖索引,一定要注意select列表中只取出需要的列,不能使select *,因为如果将所有的字段一起做索引会导致索引文件过大,查询性能下降。
表明使用了where过滤
是引用了连接缓存
你输入的内容让mysql错乱了,where子句的值总是false,不能用来回去任何元组
在没有group by子句的情况下,基于索引有啊MIN/MAX操作或者对于myisam存储索引优化count(*)操作,不必等到执行阶段在进行计算,查询执行计划生成的阶段即完成优化
优化distinct操作,在找到第一匹配的元组后即停止找同样的动作