一.InnoDB索引

  InnoDB支持以下几种索引:

  • B+树索引
  • 全文索引
  • 哈希索引

  本文将着重介绍B+树索引。其他两个全文索引和哈希索引只是做简单介绍一笔带过。

  哈希索引是自适应的,也就是说这个不能人为干预在一张表生成哈希索引,InnoDB会根据这张表的使用情况来自动生成。

  全文索引是将存在数据库的整本书的任意内容信息查找出来的技术,InnoDB从1.2.x版本支持。每张表只能有一个全文检索的索引。

  B+树索引是传统意义上的索引,B+树索引并不能根据键值找到具体的行数据,B+树索引只能找到行数据锁在的页,然后通过把页读到内存,再在内存中查找到行数据。B+树索引也是最常用的最为频繁使用的索引。

二.什么是B+树

概念

  B+树是一种平衡查找树,其实先想想看为什么要用平衡查找树,不用二叉树?普通的二叉树可能因为插入的数据最后变成一个很长的链表,怎么能提高搜索的速度呢?你可以想想,为什么HashMap和ConcurrentHashMap在JDK8的时候,当链表大于8的时候把链表转成红黑树(红黑树也是平衡查找树)。技术思维是想通的,那么答案无非是加快速度,性能咯。

  一个B+树有以下特征:

  • 有n个子树的中间节点包含n个元素,每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。
  • 所有叶子节点包含元素的信息以及指向记录的指针,且叶子节点按关键字自小到大顺序链接。
  • 所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。

  那么我们先来看一个B+树的图

  所有的数据都在叶子节点,且每一个叶子节点都带有指向下一个节点的指针,形成了一个有序的链表。为什么要有序呢?其实是为了范围查询。比如说select * from Table where id > 1 and id < 100; 当找到1后,只需顺着节点和指针顺序遍历就可以一次性访问到所有数据节点,极大提到了区间查询效率。是不是范围查询的话hash就搞不定这个事情了?以下为B+树的优势:

  • 单一节点存储更多元素,减少IO
  • 所有查询都要找到叶子节点,查询稳定
  • 所有叶子节点形成有序链表,方便范围查询

  一般性情况,数据库的B+树的高度一般在2~4层,这就是说找到某一键值的行记录最多需要2到4次逻辑IO,相当于0.02到0.04s。

三.聚集索引和辅助索引

聚集索引

  聚集索引是按表的主键构造的B+树,叶子节点存放的为整张表的行记录数据,每张表只能有一个聚集索引。优化器更倾向采用聚集索引。因为直接就能获取行数据。

  请选择自增id来做主键,不要非空UK列。避免大量分页碎片。下面来看一个聚集索引的图:

  那么很简单了,每个叶子节点,都存有完整的行记录。对于主键的查找速度那是相当的快,美滋滋。

辅助索引

  辅助索引也叫非聚集索引,叶子节点除了键值以外还包含了一个bookmark,用来告诉InnoDB在哪里可以找到对应的行数据,InnoDB的辅助索引的bookmark就是相对应行数据的聚集索引键。也就是先获取指向主键索引的主键,然后通过主键索引来找到一个完整的行。如果辅助索引的树和聚集索引的树的高度都是3,如果不是走主键索引走辅助索引的话,那么需要6次逻辑IO访问得到最终的数据页。辅助索引和聚集索引的概念关系图如下:

四.索引实战

设计索引

  设计索引的时候,无论是组合索引还是普通索引等。一般经验是,选择经常被用来过滤记录的字段,高选择性,高区分性。别把性别字段设计索引,性别属于低选择性的。你可以选择名字嘛,你好我大名叫苗嘉杏:)

  知道加索引快,但是也别乱加索引,插入以及更新索引的操作InnoDB都会维护B+树的,多加很多索引只会导致效率降低!

  不要用重复的索引,比如有个联合索引是a,b,你又整个a列的普通索引。那不是搞事么?

  不要在索引上用函数和like

一颗聚集索引B+树可以放多少行数据?

  这里我们先假设B+树高为2,即存在一个根节点和若干个叶子节点,那么这棵B+树的存放总记录数为:根节点指针数*单个叶子节点记录行数。假设一行记录的数据大小为1k,那么单个叶子节点(页)中的记录数=16K/1K=16。

  那么现在我们需要计算出非叶子节点能存放多少指针,我们假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,这样一共14字节,我们一个页中能存放多少这样的单元,其实就代表有多少指针,即16kb/14b=1170。那么可以算出一棵高度为2的B+树,大概能存放1170*16=18720条这样的数据记录。

  根据同样的原理我们可以算出一个高度为3的B+树大概可以存放:1170*1170*16=21902400行数据。所以在InnoDB中B+树高度一般为1-3层,它就能满足千万级的数据存储。在查找数据时一次页的查找代表一次IO,所以通过主键索引查询通常只需要1-3次逻辑IO操作即可查找到数据。

Cardinality值

  如何判断一个索引建立的是否好呢?可以用show index from指令查看Cardinality值,这个值是一个预估值,而不是一个准确值。每次对Cardinality值的统计都是随机取8个叶子节点得到的。

  对于innodb来说,达到以下2点就会重新计算cardinality

  • 如果表中1/16的数据发生变化
  • 如果stat_modified_counter>200 000 0000

  实际应用中,(Cardinality/行数)应该尽量接近1。如果非常小则要考虑是否需要此索引。实战一下,比如有一张表,我们来show index一下

mysql> show index from Order;
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Order | 0 | PRIMARY | 1 | id | A | 99552 | NULL | NULL | | BTREE | | |
| Order | 1 | IDX_orderId | 1 | orderId | A | 96697 | NULL | NULL | | BTREE | | |
| Order | 1 | IDX_productId | 1 | productId | A | 52 | NULL | NULL | | BTREE | | |
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.00 sec)

  那么可以看到IDX_productId这个索引的Cardinality比较低。 

  需要强制刷新Cardinality值的话可以用:

analyze local table xxx;

参考:

MySQL5.1参考手册 - http://dev.mysql.com/doc/refman/5.1/zh/index.html

《MySQL技术内幕》

《小灰漫画》

https://www.cnblogs.com/leefreeman/p/8315844.html

http://blog.codinglabs.org/articles/theory-of-mysql-index.html

 

搞懂MySQL InnoDB B+树索引的更多相关文章

  1. 搞懂MySQL(各种)索引类型及其区别

    索引的概念介绍: 1.聚集索引 聚集索引:指索引项的排序方式和表中数据记录排序方式一致的索引  也就是说聚集索引的顺序就是数据的物理存储顺序.它会根据聚集索引键的顺序来存储表中的数据,即对表的数据按索 ...

  2. 搞懂MySQL InnoDB事务ACID实现原理

    前言 说到数据库事务,想到的就是要么都做修改,要么都不做.或者是ACID的概念.其实事务的本质就是锁和并发和重做日志的结合体.那么,这一篇主要讲一下InnoDB中的事务到底是如何实现ACID的. 原子 ...

  3. 一文快速搞懂MySQL InnoDB事务ACID实现原理(转)

    这一篇主要讲一下 InnoDB 中的事务到底是如何实现 ACID 的: 原子性(atomicity) 一致性(consistency) 隔离性(isolation) 持久性(durability) 隔 ...

  4. MySQL的B+树索引和hash索引的区别

    简述一下索引: 索引是数据库表中一列或多列的值进行排序的一种数据结构:索引分为聚集索引和非聚集索引,聚集索引查询类似书的目录,快速定位查找的数据,非聚集索引查询一般需要再次回表查询一次,如果不使用索引 ...

  5. SQL优化 MySQL版 - B树索引详讲

    SQL优化 MySQL版  - -B树索引详讲 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 为什么要进行SQL优化呢?很显然,当我们去写sql语句时: 1会发现性能低 2.执行时间太 ...

  6. MySQL InnoDB表和索引之聚簇索引与第二索引

    MySQL InnoDB表和索引之聚簇索引与第二索引 By:授客QQ:1033553122 每个InnoDB表都有一个称之为聚簇索引(clustered index)的特殊索引,存储记录行数据.通常, ...

  7. 彻底搞懂MySQL为什么要使用B+树索引

    目录 MySQL的存储结构 表存储结构 B+树索引结构 B+树页节点结构 为什么要用B+树索引 二叉树 多叉树 B树 B+树 搞懂这个问题之前,我们首先来看一下,MySQL表的存储结构 MySQL的存 ...

  8. 一本彻底搞懂MySQL索引优化EXPLAIN百科全书

    1.MySQL逻辑架构 日常在CURD的过程中,都避免不了跟数据库打交道,大多数业务都离不开数据库表的设计和SQL的编写,那如何让你编写的SQL语句性能更优呢? 先来整体看下MySQL逻辑架构图: M ...

  9. 一文搞懂mysql索引底层逻辑,干货满满!

    一.什么是索引 在mysql中,索引是一种特殊的数据库结构,由数据表中的一列或多列组合而成,可以用来快速查询数据表中有某一特定值的记录.通过索引,查询数据时不用读完记录的所有信息,而只是查询索引列即可 ...

随机推荐

  1. [Usaco2009 Jan]安全路经Travel BZOJ1576 Dijkstra+树链剖分+线段树

    分析: Dijkstra求最短路树,在最短路树上进行操作,详情可见上一篇博客:http://www.cnblogs.com/Winniechen/p/9042937.html 我觉得这个东西不压行写出 ...

  2. Python入门:购物车实例

    product_list=[('iphone',5800), ('pro',120000), ('python book',120), ('Bike',800), ('coffe',39)] #定义商 ...

  3. 终于将SAP系统完全配置通过了

    花了近10天的时间,每天晚上加班加点,终于将SAP S4 1610 IDES系统从零到有,从头到尾配置一遍.目前只启用了一家模拟公司,从基础数据的设置,到销售订单开立(含按单按库需求),跑MRP需求, ...

  4. 《HelloGitHub》第 37 期

    公告 欢迎熟悉 C# 热爱开源的小伙伴加入我们,点此联系我 <HelloGitHub>第 37 期 兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub ...

  5. 有道云笔记MarkDown 插入图片

    前言: 在网上找了很多有道云笔记的markdown笔记如何插入本地图片,试了好几种方式都是一时可以显示而已,只要电脑重启或者换终端查看就无法显示图片了.网上常用的方法无非两种有效:github.博客. ...

  6. 开发人员必备工具 —— JMeter 压测

    在接口开发完以后,开发人员应该学会对自己的接口先进行压测一下,虽然压测的结果并不一定准确,也不能完全反映真实情况,但是如果有问题的话多少是可以看出的,而且也可以及早做优化,做到心里有底.否则,等测试进 ...

  7. ORM 开发环境之利器:MVC 中间件 FreeSql.AdminLTE

    前言 这是一篇纯技术干货的分享文章,FreeSql 已经基本完成 .NETCore 最方便的 ORM 使命,我们正在筹备生态的建立,比如 ABP 中如何使用 FreeSql 的实现,需要各种各样的扩展 ...

  8. MySQL · 引擎特性 · InnoDB崩溃恢复

    前言 数据库系统与文件系统最大的区别在于数据库能保证操作的原子性,一个操作要么不做要么都做,即使在数据库宕机的情况下,也不会出现操作一半的情况,这个就需要数据库的日志和一套完善的崩溃恢复机制来保证.本 ...

  9. MySQL8.0新特性——支持原子DDL语句

    MySQL 8.0开始支持原子数据定义语言(DDL)语句.此功能称为原子DDL.原子DDL语句将与DDL操作关联的数据字典更新,存储引擎操作和二进制日志写入组合到单个原子事务中.即使服务器在操作期间暂 ...

  10. 设计模式之创建类模式PK

    创建类模式包括: 工厂方法模式 建造者模式 抽象工厂模式 单例模式 原型模式 创建类模式能够提供对象的创建和管理职责. 其中单例模式和原型模式非常容易理解, 单例模式是要保持在内存中只有一个对象,原型 ...