mysql之索引那些事儿~
磁盘预读
4096字节 block
b树
balance tree

b+树
数据只存储在叶子节点
在子节点之间加入了双向地址连接,更方便的在子节点之间进行数据的读取

索引原理
innodb索引
# 聚集索引 一个表只有一个主键,即聚集索引
# 辅助索引 除了主键之外所有的索引都是辅助索引,回表: 只查询一个索引并不能解决查询中的问题,还需要到具体的 表中去获取正行数据
myisam索引
# 辅助索引 除了主键之外所有的索引都是辅助索引
索引的种类
数据库中的B+树索引可以分为聚集索引(clustered index)和辅助索引(secondary index)
-
聚集索引
- InnoDB存储引擎表是索引组织表,即表中数据按照主键顺序存放。而聚集索引(clustered index)就是按照每张表的主键构造一棵B+树,同时叶子结点存放的即为整张表的行记录数据,也将聚集索引的叶子结点称为数据页。聚集索引的这个特性决定了索引组织表中数据也是索引的一部分。同B+树数据结构一样,每个数据页都通过一个双向链表来进行链接。
- 由于实际的数据页只能按照一棵B+树进行排序,因此每张表只能拥有一个聚集索引。在多数情况下,查询优化器倾向于采用聚集索引。因为聚集索引能够在B+树索引的叶子节点上直接找到数据。
此外由于定义了数据的逻辑顺序,聚集索引能够特别快地访问针对范围值得查询。 - 聚集索引的好处:它对主键的排序查找和范围查找速度非常快,叶子节点的数据就是用户所要查询的数据。如用户需要查找一张表,查询最后的10位用户信息,由于B+树索引是双向链表,所以用户可以快速找到最后一个数据页,并取出10条记录。范围查询(range query)即如果要查找主键某一范围内的数据,通过叶子节点的上层中间节点就可以得到页的范围,之后直接读取数据页即可**
-
辅助索引
-
表中除了聚集索引外其他索引都是辅助索引(Secondary Index,也称为非聚集索引),与聚集索引的区别是:辅助索引的叶子节点不包含行记录的全部数据。叶子节点除了包含键值以外,每个叶子节点中的索引行中还包含一个书签(bookmark)。该书签用来告诉InnoDB存储引擎去哪里可以找到与索引相对应的行数据。由于InnoDB存储引擎是索引组织表,因此InnoDB存储引擎的辅助索引的书签就是相应行数据的聚集索引键。
-
辅助索引的存在并不影响数据在聚集索引中的组织,因此每张表上可以有多个辅助索引,但只能有一个聚集索引。当通过辅助索引来寻找数据时,InnoDB存储引擎会遍历辅助索引并通过叶子级别的指针获得只想主键索引的主键,然后再通过主键索引来找到一个完整的行记录。
举例来说,如果在一棵高度为3的辅助索引树种查找数据,那需要对这个辅助索引树遍历3次找到指定主键,如果聚集索引树的高度同样为3,那么还需要对聚集索引树进行3次查找,最终找到一个完整的行数据所在的页,因此一共需要6次逻辑IO访问才能得到最终的一个数据页。
-
-
聚集索引与辅助索引相同的是:不管是聚集索引还是辅助索引,其内部都是B+树的形式,即高度是平衡的,叶子结点存放着所有的数据。
-
聚集索引与辅助索引不同的是:叶子结点存放的是否是一整行的信息
priamry key 的创建自带索引效果 非空 + 唯一 ---------》 聚集索引
unique 唯一约束的创建也自带索引效果 唯一 --------------》辅助索引
index 普通的索引 --------------》辅助索引
创建索引
create index ind_name on 表(name);
删除索引
drop index ind_name on 表;
索引的优缺点
优点 : 查找速度快,创建了索引之后的效率大幅度提高
缺点 : 浪费空间,拖慢写的速度,文件所占的硬盘资源也大幅度提高
不要在程序中创建无用的索引
正确的使用索引
1.所查询的列是创建了索引的列
2.在条件中不能带运算或者函数,必须是"字段 = 值"
3.如果创建索引的列的内容重复率高也不能有效利用索引
# 重复率不超过10%的列比较适合做索引
4.数据对应的范围如果太大的话,也不能有效利用索引
# between and > < >= <= != not in
5.like如果把%放在最前面也不能命中索引
6.多条件的情况
# and 只要有一个条件列是索引列就可以命中索引
# or 只有所有的条件列都是索引才能命中索引
7.联合索引
# 在多个条件相连的情况下,使用联合索引的效率要高于使用单字段的索引
# where a=xx and b=xxx;
# 对a和b都创建索引 - 联合索引
# create index ind_mix on s1(id,email)
1.创建索引的顺序id,email 条件中从哪一个字段开始出现了范围,索引就失效了
# select * from s1 where id=1000000 and email like 'eva10000%' 命中索引
# select count(*) from s1 where id > 2000000 and email = 'eva2000000' 不能命中索引
2.联合索引在使用的时候遵循最左前缀原则
# select count(*) from s1 where email = 'eva2000000@oldboy';
3.联合索引中只有使用and能生效,使用or失效

浙公网安备 33010602011771号