mysql索引操作

mysql索引操作

索引初识

什么是索引

  • 索引相当于mysql的一种键,是存储引擎能快速找到数据的一种数据结构,具有非常好的性能,尤其当表中数据很多时,索引就显得尤为重要,索引优化是数据查询性能优化的最有效的手段,它能将数据查询速度提升几个数量级

既然索引如此优秀,是不是索引越多越好?

  • 答案当然是否定的,索引可以极快的加快查询速度,但是插入索引是个很占内存的事情,插入过多的索引会使得IO操作时间增加,而且插入索引很费时间,总的一点就是索引是典型的以空间换时间,所以我们需要合理的平衡索引的使用

索引原理

磁盘IO

  • 我们通过指令访问数据库,数据库会在硬盘中寻找数据,每次读取数据花费的时间可以分为寻道时间、旋转延迟、传输时间三个部分,磁盘IO主要包括寻道时间、旋转延迟以及传输时间。
    • 磁盘读取数据靠的是机械运动,寻道时间指的是磁臂移动到指定磁道所需要的时间,主流磁盘一般在5ms以下;
    • 旋转延迟就是我们经常听说的磁盘转速,比如一个磁盘7200转,表示每分钟能转7200次,也就是说1秒钟能转120次,旋转延迟就是1/120/2 = 4.17ms;
    • 传输时间指的是从磁盘读出或将数据写入磁盘的时间,一般在零点几毫秒,相对于前两个时间可以忽略不计
    • 那么访问一次磁盘的时间,即一次磁盘IO的时间约等于5+4.17 = 9ms=0.01s,这对于我们人来说是个微不足道的事情,因为我们人眨一次眼睛就需要0.3s,但是对计算机cpu而言这是一个巨大的时间浪费,因为cpu每秒大概可以处理5亿条指令,那么一次磁盘IO时间cpu可以处理5百万条指令,所以我们需要加快查询效率,尽量减少磁盘IO的次数

磁盘预读

  • 基于磁盘IO原理,我们应该减少磁盘IO次数,所以计算机做了优化,即会在每次从磁盘中读取数据的时候多读出一些数据来到内存中(它认为你马上就会使用到接下来的数据),这个数据大小是固定的,大概是4kb或者8kb,不同操作系统读取数据大小不同,Linux可在系统中设置读取数据大小,默认为4kb,也叫一个block

索引数据结构

  • 索引的数据结构为B+树
    • b(balance),也就是平衡树,B树是在二叉树的基础之上进行改良得到的,它的作用是保证每一次数据查询所经历的IO次数一致
  • B+树同样在B树的基础上做了一些强化,比如:
    • 保持树的高度,保证每一次数据查询所经历的IO次数一致
    • B+树不在分支节点存储数据,只在叶子节点上存储数据,这样就可以极大减少树的高度,一般为2-4层,极大减少IO次数
    • B+树在相邻叶子节点上增加了双向链表,这样会极大加快范围型数据的查询

索引类型

  • 索引分为聚集索引(聚簇索引)和辅助索引(非聚集索引、非聚簇索引)两种,两者各有异同
    • 相同的是:不管是聚集索引还是辅助索引,其内部都是B+树的形式,即高度是平衡的,叶子结点存放着所有的数据。
    • 聚集索引与辅助索引不同的是:叶子结点存放的是否是一整行的信息
  • innodb有且只有一个聚集索引
    • 主键会默认自带聚集索引+非空+唯一
    • unique默认自带辅助索引+唯一

索引的创建和删除

  • 创建
    • create index 索引名 on 表名(字段名);
      • create index ind_age on t1(age);
    • create index 索引名 on 表名(字段名1,字段名2,……) ; :创建一个联合索引
      • create index ind_mix on t1(age,name,sex) ;
  • 删除
    • drop index 索引名 on 表名
      • drop index ind_age on t1;

如何正确使用mysql数据库

从库的角度出发

  • 搭建集群
  • 读写分离
  • 分库

从表的角度出发

  • 合理的安排表与表之间的关系:该拆就拆,该合就合
  • 尽量把固定长度的字段放在前面
  • 尽量使用char类型而不是varchar类型

从数据角度出发

  • 在where处尽量将筛选范围缩小到一个足够小的范围:分页
  • 尽量使用连表查询而不是子查询
  • 删除或修改数据的时候尽量使用主键
  • 合理创建和使用索引

合理创建和使用索引

创建索引
  • 选择区分度比较大的字段作为索引
    • 大概<1/10相似度的即可,性别之类的字段不适合做索引
  • 选择长度小的字段做索引
  • 及时删除不必要的索引,节省存储空间
使用索引
  • 查询的字段不是索引字段
  • 范围查询时,范围越大,查询越慢,范围越小,查询越快
    • 数据很多的情况下:where age>10 或者 where age!=1之类查询比较慢
    • 数据很多的情况下:where age>100000或者where=2的情况就查询很快
  • like分为两种情况
    • where name like 'a%':这种情况查询速度很快
    • where name like '%a':这种情况查询速度很慢
  • 当对索引字段进行计算或者使用函数的时候查询比较慢,所以要保持索引的干净度
  • and和or
    • and : where age and sex这种查询速度较快,只要查询字段中有索引字段就会命中索引
    • or :where age and sex这种查询速度较慢,只要age和sex都是索引字段时才会快
  • 最左前缀匹配原则(联合索引)
    • 对于组合索引mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配(指的是范围大了,有索引速度也慢)
  • 查询索引字段但使用的类型与索引字段不一致时,查询会很慢
  • select 字段中在包含oreder by 中的字段时查询速度才快

覆盖索引

  • 覆盖索引就是在查询数据的时候可以直接在辅助索引的叶子节点中得到数据,不需要回表到聚集索引中寻找数据

索引合并(联合索引)

  • 分别创建的两个索引可以合并为一个联合索引,一般在and和or中使用,如a=1 or b=10时可以创建联合索引

执行计划

  • 能够查询sql语句有没有按照预期执行,可以查看索引使用情况以及type等级
    • explain sql执行语句

慢查询优化

0.先运行看看是否真的很慢,注意设置SQL_NO_CACHE
1.where条件单表查,锁定最小返回记录表。这句话的意思是把查询语句的where都应用到表中返回的记录数最小的表开始查起,单表每个字段分别查询,看哪个字段的区分度最高
2.explain查看执行计划,是否与1预期一致(从锁定记录较少的表开始查询)
3.order by limit 形式的sql语句让排序的表优先查
4.了解业务方使用场景
5.加索引时参照建索引的几大原则
6.观察结果,不符合预期继续从0分析

mysql慢日志

  • 在mysql中开启并设置
  • 当有mysql语句的执行时间超过设定的时间时会将这条sql语句记录下来
  • 这个时候我们就可以查看mysql慢日志去实现定期的优化
posted @ 2020-06-03 16:58  yyyzh  阅读(233)  评论(0编辑  收藏  举报