MySql性能调优
索引的定义
索引(Index)是帮助MySQL高效获取数据的数据结构
数据本身之外,数据库还维护着一个满足特定查找算法的数据结构,这些数据结构以某种方式指向数据,这样就可以在这些数据结构的基础上实现高阶查找算法,这种数据结构,就是索引
索引可以简单的理解为:排好序的快速查找的数据结构
一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以文件的形式存储在磁盘上
我们平常所说的所有,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉树)结构组织的索引,其中聚集索引,次要索引,复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称:索引,当然,除了B+树这种类型的索引之外,还有哈希索引
索引的好处与劣势
- 好处:
- 类似大学图书馆建书目录,提供数据检索的效率,降低数据库的IO成本
- 通过索引列队数据进行排序,降低数据排序的成本,降低了CPU的消耗
- 劣势
- 实际上索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占用空间的
- 虽然索引大大提高查询速度,同时也会降低跟新表的速度,如对表进行insert、update、delete,因为更新表时,MySQL
不仅要保存数据,还要保存一下索引文件每次更新添加了索引列的地段,都会调整因为更新带来的键值变化后的索引信息 - 索引只是提高效率的一个因素,如果你的MySQL有大数量的表,就需要花时间研究建立最优秀的索引
索引的分类
单值索引:即一个索引包含单个列,一个表可以有多个单例索引
- 唯一索引:索引列的值必须唯一,单允许有空值
- 复合索引:一个索引包含多个列
创建:create index indexName on mytable(columnname(lenght))
alter mytable add index [indexName] on (columnname(lenght))
删除:drop index [indexName] on mytable;
查看:show index from table_name\G
索引的原理
那些情况需要创建索引
- 主键自动建立唯一索引
- 频繁作为查询条件的字段应该创建索引
- 查询中与其他表关联的字段,外键关系建立索引
- 频繁更新的字段不适合创建索引,因为每次不单单更新记录还会更新索引值
- Where条件里面用不到的字段不创建索引
- 高并发适合创建组合索引
- 查询中统计或者分组字段
MySQL常见瓶颈
- cpu:CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据的时候
- IO:磁盘I/O瓶颈发生在装入数据远大于内存容量的时候
- 服务器硬件的性能瓶颈:top,free,iostat和vmstat来查看系统的性能状态
explain
explain执行计划:是explain关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如果处理SQL语句的,分析你的查询语句或是表结构的性能瓶颈
id
select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序
1.ID相同,执行顺序从上到下
2.ID不同,如果是子查询,ID的序号会递增,ID值越大优先级越高,越先被执行,下面的执行顺序是:t3表->t2表->t1表
3.id如果相同,可以认为是同一组,从上往下顺序执行,在所有组中,ID值越大,优先级越高,越先执行 ,devived(衍生,一般只虚表如s1)
select_type
select_type的几种类型:
类型 | 解释 |
---|---|
Simple | 简单的select查询,查询中不包含子查询或union |
primary | 查询中若包含任何仿复杂的子查询,最外层查询则被标记为primary(被primary标记的最后执行) |
subquery | 在select或where列表中包含了子查询 |
derived | 在from列表中包含的子查询被标记为derived(衍生),MySQL会递归执行这些子查询,把结果放在临时表里 |
union | 若第二个select出现在union之后,则标记为union;若union包含在from字句的子查询中,外层的select将被标记为:derived |
union_result | 从union表获取结果的select |
type
显示查询使用了何种类型:
$从最好到最差的依次顺序是:system > const > eq_ref > ref > range > index > all$
一般来说,得保证至少达到range级别,最好达到ref
类型 | 解释 |
---|---|
system | 表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个可以忽略不计 |
const | 表示通过索引一次就找到了,const用于比较primary key或者unique索引,因为只匹配一行数据,所以很快,如将主键置于where列表中,MySQL就能将该查询转换为一个常量 |
eq_ref | 唯一索引扫描,对于每一个索引值,表中只有一条记录与之匹配,常见于主键或者唯一索引扫描 |
ref | 非唯一索引扫描,返回匹配某个单独值的所有行,然而,它可能会找到多个符合条件的行,所以它应该属于查找和扫描的混合体 |
range | 只检索给定范围的行,使用一个索引来进行选择,key列显示使用了哪个索引,一般就是你的where语句中出现了between、<、>、in等的查询,中范围扫描索引比全表扫描要好,因为它只需要开始于索引指定的某一点,而结束于另一点,不用全表扫描 |
index | Full Index Scan,index于All区别为index类型只遍历索引,这通常比All要快,因为索引文件通常比数据文件小,(也就是说虽然Full和Index都是读全表,但是index是从索引中读取的,而all是从硬盘中读取的 |
all | Full Table Scan,将遍历全表找到匹配的行 |
possible_keys
- 显示可能应用在这张表中的索引,一个或多个
- 查询涉及到字段上若存在索引,则该索引将被列出,但不一定被查询时间应用
key
1.实际中使用的索引,如果为NUll,则没有使用索引
2. 查询中若使用了覆盖索引,则该索引仅出现在key列表中
key_len
1.表示索引中使用的字节数,可以通过该值计算查询中使用的索引的长度,在不损失精确性的情况下,长度越短约好
2. key_len显示的为索引字段的最大可能长度,并非时间使用长度,即key_len是根据表定义计算而得,不是通过表内检索出来的
ref
显示索引的那一列被使用了,如果可能的话,是一个常数,哪些列或者常量被用于查找索引列上的值
rows
根据表统计信息以及索引选用情况,大致估算出找到所需要的记录所需要的行数