mysql优化
性能下降的原因
查询语句写的不友好,各种连接,各种子查询导致用不上的索引或者没有建立索引
建立的索引失效 建立了索引在真正执行时,没有用上建立索引
关联查询太多join
服务器调优和个配置参数导致 如果设置的不合理比例不恰当,也会导致性能下降sql变慢
索引
索引帮助mysql高效获取数据的的数据结构
索引就是数据结构
类似新华字典的索引目录,可以通过-索引目录快速查到你想要的字
为什么要建立索引
提高查询效率,没有排序之前一个一个找,通过索引排序之后,可以直接定位到想要的位置
排好序的快速查找数据结构就是索引
优势
类似大学图书馆建立的书目索引,提高数据检索的效率,降低数据库的io成本
通过索引对数据项目进行排序,降低数据排序成本,降低了cpu的消耗
劣势
一般来说,索引本身也很大,索引旺旺以文件形式存储到磁盘上
索引也是一张表,保存了主键与索引字段,并指向实体表的记录,所以索引也是要占磁盘空间的
虽然提高了查询的速度,但是会降低更新表的速度(因为同时要对索引进行更新)
分类
单值索引:一个索引只包含个列,一个表可以有多个单值索引 一半来说建立索引不要超过5个
唯一索引:索引列的值必须唯一,但允许有空值
复合索引:一个索引包含多个列
全文索引:mysql全文检索是利用查询关键字和查询列内容之间的相关度进行检索,可以利用全文索引来提高匹配度
原理
在我们存数据时, 如果建立索引
数据库系统会维护一个满足特定查找算法的数据结构,这些数据结构以某种方式引用数据
可以在这些数据结构之上,实现高级查找算法,这种结构就是索引
一般来说, 索引本身也很大, 不可能全部存储在内存中, 因此索引往往以索引文件的形式存储在磁盘上
为了加快数据的查找,可以维护二叉查找树, 每个节点分别包含索引键值和一个指向对应数据记录的物理地址的指针,
这样就可以运用二叉查找在一定的复杂度内获取相应的数据,从而快速的检索出符合条件 的记录
除了二叉树还有BTtree索引
我平时所说的索引,如果没有特别指定, 都是指B树结构组织的索引
其中聚焦索引,次要索引,复合索引,前缀索引,唯一默认都是B+树索引
除B+树索引之外, 还有哈希索引(Hash index)等
二叉树查找,一个数据最多有俩个分支,小分支放在左边大分支放在右边,当前数据小就往左边查找
索引建立选择
适合建立索引
- 主键自动建立唯一索引
频繁作为查询条件的字段应该创建索引
查询中与其他表关联的字段
查询排序的字段,排序的字段通过索引去访问将若通过索引访问将大大提升排序速度,索引能加快查找和排序的速度
查询中统计或分组的字段,
不适合建立索引
频繁更新的字段不适合建立索引
where条件里用不到的字段不建立索引
记录比较少
经常增删改的表,索引提高了查询的速度同时会降低更新表的速度,因为建立索引后更新表时,mysql不不仅要保存数据还要保存一下索引文件
数据重复的表字段
表的设计规则
数据库设三范式
第一范式:数据库的表一列都是不可分割的基本数据项,同意列中不能有多个值
对关系型数据库的基本要求,不满足第一范式就不是关系型数据库
第一范式:要求设局库表中每个实力或行可以被唯一的区分
设置主键
第三范式:要求一个数据库中不包含已在其他表中已包含的非主关键字信息
俩张表不要重复的字段,通常都是设置外键
大表拆小表
在一个数据库中,一般不会涉及属性过多的表
在一个数据库中,一般不会有超过500/1000w数据的表 拆表
有大数据的列表单独拆成小表
dql的执行过程
- 客户端发送一条查询给服务器;
- 服务器通过权限检查之后,先会检查查询缓存,如果命中了缓存,则立即返回存储在缓存中的结果。否则进入下一阶段;
- 服务器端进行SQL解析、预处理,再由优化器根据该SQL所涉及到的数据表的统计信息进行计算,生成对应的执行计划;
- MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询;
- 将结果返回给客户端。
写的任何sql,到底是怎么样真正执行的,按照什么条件查询,最后执行的顺序,可能都会有多个执行方案
查询优化器根基对数据表的统计信息(比如索引,有多少条数据),在真正执行一条sql之前,会根据自己内部的数据,进行综合的查询,
根据mysql自身的统计信息, 从多种执行方案当中, 选择一个它认为是最优的执行方案,来去执行
做优化, 就是想让查询优化器按照我们的想法,帮我们选择最优的执行方案,
让优化器选择符合程序员计划的执行语句,来减少查询过程中产生的IO
性能分析
mysql常见瓶颈
cpu饱和
磁盘i/o读取数据大小
服务器硬件配置比较低
Explain
使用explan关键字可以模拟优化器执行的sql语句
从而知道mysql是如何处理sql语句的
通过Explain可以分析查询语句或表结构的性能瓶颈
作用
查看表的读取顺序
数据读取操作的操作类型
查看哪些索引可以使用
查看哪些索引被实际使用
查看表之间的引用
查看每张表有多少行被优化器执行
id
id相同从上往下,id不同从大到小
如果是子查询id的序列号会递增,id值越大优先级越高,越先执行
select_type
作用查询类型,主要用于区别普通查询,联合查询子查询等复杂查询
结果值
- simple 简单select查询,查询中不包含子查询或者union
- primary 查询中包含任何复杂的子查询,最外层的查询被标记为primary
- SUBQUERY 在select或where中包含了子查询
- DERIVED 查询中出现临时表
- UNION与UNION RESULT 将俩个表使用UNION合并在一起的时候 UNION RESULT是合并后的表
table
当前查询的数据是关于哪张表的
partitions
如果查询是基于分区的话,会显示查询访问的分区
type
访问类型排序
结果值最好到最差
- system:表中有一行记录(系统表)这是const类型的特例,平时不会出现
- const :表示通过索引一次就找到了,const用于比较primary或者unique索引.直接查询主键或者唯一索引
- eq_ref:唯一性索引扫描 对于每个索引键,表中只有一条记录与之匹配,常见于主键或唯一索引扫描
- ref:非唯一性索引扫描,返回匹配摸个单独值的所有行,本质上也是一种索引访问,他返回所有匹配某个单独值的行可能会找到多个复合条件的行,所以他应该属于查找和扫描的混合体
- range:只检索给定范围的行,使用一个索引来选择行,key列显示使用了哪个索引,一般就是在你的where语句中出,现between<> in等查询,这种范围扫描索引比全表扫描要好,因为它只需要开始于索引的某一点.而结束语另一点,不用扫描全部索引
- index:查询的时候用到了主键
- all:将全表进行扫描,从硬盘当中读取数据,如果出现了All 切数据量非常大, 一定要去做优化
possible_keys
可能会用到的索引
key
实际用到的索引与possible_keys对应
key_len
表示所以中使用的字节数,可以通过该列计算查询中使用的索引长度
ref
索引是否被引入到,到底用了哪几个索引
row
根据统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数
filtered
满足查询的记录数量的比例,注意是百分比,不是具体记录数,值越大越好,filtered列的值依赖统计信息,并不十分准确
Extra
Using filesort
说明mysql会对数据使用一个外部的索引排序,
而不是按照表内的索引顺序进行
Mysql中无法利用索引完成排序操作称为"文件排序"
示例
Using temporary
使用了临时表保存中间结果,Mysql在对查询结果排序时, 使用了临时表,
常见于排序orderby 和分组查询group by
示例
using where
表明使用了wher过滤
using join buffer
使用了连接缓存
impossible where
where 子句的值总是false 不能用来获取任何元组
Using index
查询的列被索引覆盖,并且where筛选条件是索引的是前导列,Extra中为Using index