select语句的执行流程
1.连接器:与客户端进行TCP三次握手建立连接;校验客户端的用户名和密码;读取权限
-
查询缓存(较为鸡肋)执行更新操作,表的缓存就会被清空
-
解析器:词法分析;语法分析
-
预处理器:查询语句的字段和表是否存在;
-
优化器:选择哪个索引
-
执行器:三种方式 主键索引查询、全表扫描、索引下推
MySQL存储文件
在数据库下通常包括三个文件:
- db.opt:存放默认字符集和字符校验规则
- t_order.frm:存放表的元数据信息,主要包换表结构定义
- t_order.ibd:存放表数据
表文件结构
- 行(row):数据库的记录是按行存取的
- 页(page):InnoDB的数据是按页读写的,默认页大小为16KB
- 区(extent):当表中数据量比较大时,为索引分配空间按照区为单位分配
- 段(segment):表空间由多个段组成:索引段(存放B+树非叶子节点的集合)、数据段(存放B+树的叶子节点的区的集合)、回滚段(存放回滚数据的区的集合)
索引分类
- 按数据结构分类:B+tree索引、Hash索引、Full-text索引
- 按物理存储分类:聚簇索引、二级索引
- 按字段特性分类:主键索引、唯一索引、普通索引、前缀索引
- 按字段个数分类:单列索引、联合索引
B+tree的优势
- 相对于B tree,B+tree不在叶子节点上存储数据,可以存储更多数据,且支持范围查询
- 相对于二叉树,当数据达到千万级别,B+tree依然维持在3~4层
- 相对于Hash,可以进行范围查询
什么时候不需要索引
- 字段中存在大量重复数据,区分度低的,例:男女
- 表数据太少的
- 经常更新的字段,不利创建索引
怎么优化索引
- 前缀索引优化:使用某个字段中字符串的前几个字符建立索引
- 覆盖索引优化:建立联合索引覆盖查询的字段,从二级索引的叶子节点中直接查到,避免回表查询
- 主键索引最好是自增:当插入新数据时,直接追加,可以防止页分裂
- 防止索引失效:使用左右模糊匹配
like %xx或like %xx%;在查询条件中对索引列做了计算、函数、类型转换操作;联合索引没有正确的使用最左原则匹配;where后的条件OR,OR后的列不是索引列,索引就会失效
B+tree的特点
- B+tree的节点内容是数据页,默认大小16KB
- 只有叶子节点才存放数据,非叶子节点仅用来存放目录项作为索引
- 所有节点按照索引键大小排序,构成一个双向链表
聚簇索引与二级索引的区别
- 聚簇索引存放的是包含所有列的实际数据;二级索引存放的是主键值
- 聚簇索引有主键,则作为索引键;没有主键,选择不含NULL的唯一列作为索引键;两个都没有,自动生成一个隐式自增id列
B+tree与B tree的区别
- 单点查询:B tree的平均时间更快,但是波动更大,B+tree非叶子节点不存数据,存索引,查数据都要查到最低层
- 插入和删除效率:B+tree有大量冗余节点,直接删除,有冗余直接插入,没有冗余节点自动分裂
- 范围查询:B+tree叶子节点之间存在双向链表,便于范围查询
索引失效情况
- 使用左右模糊匹配
like %xx或`like %xx% - 在查询条件中对索引列使用函数
- 在查询条件中对索引列进行表达式计算
- 索引列发生隐式类型转换
- 联合索引没有正确的使用最左原则匹配
- where后的条件OR,OR后的列不是索引列,索引就会失效
count(*)、count(1)、count(主键字段)、count(字段)的区别
- count(主键索引)优先遍历二级索引,再遍历聚簇索引
- count(1)在表中没有二级索引的时候,效率高于count(主键索引),有则相同
- count(*) 执行过程跟 count(1) 执行过程基本一样的,性能没有什么差异
- count(字段)的效率最差,会走全表扫描
为什么InnoDB要通过遍历来计数
MyISAM引擎中,每张表都有一个meta存储row_count值。但是在InnoDB引擎中支持事务,由于MVCC,同一时间有多个查询