数据库索引整理

**

一、索引

**
1.1 索引的基础知识
在这里插入图片描述
1.各个数据页可以组成一个双向链表
2.而每个数据页中的记录又可以组成一个单向链表
每个数据页都会为存储在它里边儿的记录生成一个页目录,在通过主键查找某条记录的时候可以在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录
以其他列(非主键)作为搜索条件:只能从最小记录开始依次遍历单链表中的每条记录。
select * from user where username= '**'这样没有进行任何优化的sql语句,默认会这样做:
① 定位到记录所在的页:需要遍历双向链表,找到所在的页
②从所在的页内中查找相应的记录
由于不是根据主键查询,只能遍历所在页的单链表了
很明显,在数据量很大的情况下这样查找会很慢!

1.2 索引提高检索速度
索引为什么能加快查询速度呢?
其实就是将无序的数据变成有序(相对)
如以id为8的记录查找简要步骤:在这里插入图片描述
很明显的是:没有用索引的话我们是需要遍历双向链表来定位对应的页,现在通过“目录”就可以很快地定位到对应的页上了!其实底层结构就是B+树,B+树作为树的一种实现,能够让我们很快地查找出对应的记录。

1.3 索引降低增删改的速度
B+树是平衡树的一种,我们先来看看什么是平衡树:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。如果一棵普通的树在极端的情况下,是能退化成链表的(树的优点就不复存在了)
在这里插入图片描述
B+树是平衡树的一种,是不会退化成链表的,树的高度都是相对比较低的(基本符合矮矮胖胖(均衡)的结构)【这样一来我们检索的时间复杂度就是O(logn)】!从上一节的图我们也可以看见,建立索引实际上就是建立一颗B+树。
B+树是一颗平衡树,如果我们对这颗树增删改的话,那肯定会破坏它的原有结构。
要维持平衡树,就必须做额外的工作。正因为这些额外的工作开销,导致索引会降低增删改的速度
B+树删除和修改具体可参考:
https://www.cnblogs.com/wade-luffy/p/6292784.htm

1.4 哈希索引
除了B+树之外,还有一种常见的是哈希索引。哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可立刻定位到相应的位置,速度非常快。
在这里插入图片描述
看起来哈希索引很牛逼啊,但其实哈希索引有好几个局限(根据他本质的原理可得):

1.哈希索引也没办法利用索引完成排序
2.不支持最左匹配原则
3.在有大量重复键值情况下,哈希索引的效率也是极低的---->哈希碰撞问题。
4.不支持范围查询
hash索引和b+tree索:http://www.cnblogs.com/zengkefu/p/5647279.html

1.5 InnoDB支持哈希索引吗?
主流的还是使用B+树索引比较多,对于哈希索引,InnoDB是自适应哈希索引的(hash索引的创建由InnoDB存储引擎引擎自动优化创建,我们干预不了)

1.6 聚集和非聚集索引
简单概括:
聚集索引就是以主键创建的索引
非聚集索引就是以非主键创建的索引
区别:
聚集索引在叶子节点存储的是表中的数据
非聚集索引在叶子节点存储的是主键和索引列
使用非聚集索引查询出数据时,拿到叶子上的主键再去查到想要查找的数据。(拿到主键再查找这个过程叫做回表)
非聚集索引也叫做二级索引,不用纠结那么多名词,将其等价就行了~

非聚集索引在建立的时候也未必是单列的,可以多个列来创建索引。
此时就涉及到了哪个列会走索引,哪个列不走索引的问题了(最左匹配原则–>后面有说)
创建多个单列(非聚集)索引的时候,会生成多个索引树(所以过多创建索引会占用磁盘空间)
在这里插入图片描述
在创建多列索引中也涉及到了一种特殊的索引–>覆盖索引
我们前面知道了,如果不是聚集索引,叶子节点存储的是主键+列值
最终还是要“回表”,也就是要通过主键再查找一次。这样就会比较慢
覆盖索引就是把要查询出的列和索引是对应的,不做回表操作!
比如说:
现在我创建了索引 (username,age),在查询数据的时候: select username,age from user where username= ‘**’ and age = 20。
很明显地知道,我们上边的查询是走索引的,并且,要查询出的列在叶子节点都存在!所以,就不用回表了~
所以,能使用覆盖索引就尽量使用吧~

1.7索引最左匹配原则
最左匹配原则:
索引简单如一个列 (a),也可以复杂如多个列 (a,b,c,d),即联合索引。
如果是联合索引,那么key也由多个列组成,同时,索引只能用于查找key是否存在(相等),遇到范围查询 (>、<、between、like左匹配)等就不能进一步匹配了,后续退化为线性查找。
因此,列的排列顺序决定了可命中索引的列数。
例子:

如有索引 (a,b,c,d),查询条件 a = 1 and b = 2 and c > 3 and d = 4,则会在每个节点依次命中a、b、c,无法命中d。(c已经是范围查询了,d肯定是排不了序了)
为什么能命中c?

举个简单例子: select * from user where age > 30

1.8索引总结
索引在数据库中是一个非常重要的知识点!上面谈的其实就是索引最基本的东西,要创建出好的索引要顾及到很多的方面:
1,最左前缀匹配原则。这是非常重要、非常重要、非常重要(重要的事情说三遍)的原则,MySQL会一直向右匹配直到遇到范围查询 (>,<,BETWEEN,LIKE)就停止匹配。
2,尽量选择区分度高的列作为索引,区分度的公式是 COUNT(DISTINCT col)/COUNT(*)。表示字段不重复的比率,比率越大我们扫描的记录数就越少。
3,索引列不能参与计算,尽量保持列“干净”。比如:FROM_UNIXTIME (create_time) = ‘2016-06-06’ 就不能使用索引,原因很简单,B+树中存储的都是数据表中的字段值,但是进行检索时,需要把所有元素都应用函数才能比较,显然这样的代价太大。所以语句要写成 : create_time=UNIX_TIMESTAMP(‘2016-06-06’)。
4,尽可能的扩展索引,不要新建立索引。比如表中已经有了a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
5,单个多列组合索引和多个单列索引的检索查询效果不同,因为在执行SQL时,MySQL只能使用一个索引,会从多个单列索引中选择一个限制最为严格的索引(经指正,在MySQL5.0以后的版本中,有“合并索引”的策略,翻看了《高性能MySQL 第三版》,书作者认为:还是应该建立起比较好的索引,而不应该依赖于“合并索引”这么一个策略)。
“合并索引”策略简单来讲,就是使用多个单列索引,然后将这些结果用“union或者and”来合并起来

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值