InnoDB引擎表的特点

1、InnoDB引擎表是基于B+树的索引组织表(IOT)

关于B+树

(图片来源于网上)

B+ 树的特点:

(1)所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;

(2)不可能在非叶子结点命中;

(3)非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层;

2、如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引、如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引、如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。

3、数据记录本身被存于主索引(一颗B+Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)

4、如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页

5、如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

综上总结,如果InnoDB表的数据写入顺序能和B+树索引的叶子节点顺序一致的话,这时候存取效率是最高的,也就是下面这几种情况的存取效率最高:

1、使用自增列(INT/BIGINT类型)做主键,这时候写入顺序是自增的,和B+数叶子节点分裂顺序一致;

2、该表不指定自增列做主键,同时也没有可以被选为主键的唯一索引(上面的条件),这时候InnoDB会选择内置的ROWID作为主键,写入顺序和ROWID增长顺序一致;
除此以外,如果一个InnoDB表又没有显示主键,又有可以被选择为主键的唯一索引,但该唯一索引可能不是递增关系时(例如字符串、UUID、多字段联合唯一索引的情况),该表的存取效率就会比较差。

《高性能MySQL》中的原话

我们先了解下InnoDB引擎表的一些关键特征:

  • InnoDB引擎表是基于B+树的索引组织表(IOT);
  • 每个表都需要有一个聚集索引(clustered index);
  • 所有的行记录都存储在B+树的叶子节点(leaf pages of the tree);
  • 基于聚集索引的增、删、改、查的效率相对是最高的;
  • 如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择器作为聚集索引;
  • 如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引;
  • 如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。

综上总结,如果InnoDB表的数据写入顺序能和B+树索引的叶子节点顺序一致的话,这时候存取效率是最高的,也就是下面这几种情况的存取效率最高:

  • 使用自增列(INT/BIGINT类型)做主键,这时候写入顺序是自增的,和B+数叶子节点分裂顺序一致;
  • 该表不指定自增列做主键,同时也没有可以被选为主键的唯一索引(上面的条件),这时候InnoDB会选择内置的ROWID作为主键,写入顺序和ROWID增长顺序一致;
  • 除此以外,如果一个InnoDB表又没有显示主键,又有可以被选择为主键的唯一索引,但该唯一索引可能不是递增关系时(例如字符串、UUID、多字段联合唯一索引的情况),该表的存取效率就会比较差。

附图:

1、B+树典型结构

2、InnoDB主键逻辑结构

延伸阅读:

1、 TPCC-MySQL使用手册

2、 B+Tree index structures in InnoDB

3、 B+Tree Indexes and InnoDB – Percona

4、 MySQL官方手册: Clustered and Secondary Indexes

mysql中InnoDB表为什么要建议用自增列做主键的更多相关文章

  1. (转)mysql中InnoDB表为什么要建议用自增列做主键

    InnoDB引擎表的特点 1.InnoDB引擎表是基于B+树的索引组织表(IOT) 关于B+树 (图片来源于网上) B+ 树的特点: (1)所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关 ...

  2. [MySQL FAQ]系列 — 为什么InnoDB表要建议用自增列做主键

    我们先了解下InnoDB引擎表的一些关键特征: InnoDB引擎表是基于B+树的索引组织表(IOT): 每个表都需要有一个聚集索引(clustered index): 所有的行记录都存储在B+树的叶子 ...

  3. InnoDB表要建议用自增列做主键

    InnoDB引擎表是基于B+树的索引组织表(IOT): 每个表都需要有一个聚集索引(clustered index): 所有的行记录都存储在B+树的叶子节点(leaf pages of the tre ...

  4. MySQL面试题之为什么要为innodb表设置自增列做主键?

    为什么要为innodb表设置自增列做主键? 1.使用自增列做主键,写入顺序是自增的,和B+数叶子节点分裂顺序一致 2.表不指定自增列做主键,同时也没有可以被选为主键的唯一索引,InnoDB就会选择内置 ...

  5. mysql中,通过脚本设置表的自增列,及自增步长

    设置自增列(其实通过navicate可以直接设置的,也方便:要不然可能需要删除列了) ALTER TABLE `domain_dns_tucows` CHANGE `id` `id` INT(11) ...

  6. 《MySQL实战45讲》学习笔记4——MySQL中InnoDB的索引

    索引是在存储引擎层实现的,且在 MySQL 不同存储引擎中的实现也不同,本篇文章介绍的是 MySQL 的 InnoDB 的索引. 下文将以这张表为例开展. # 创建一个主键为 id 的表,表中有字段 ...

  7. MySql中innodb存储引擎事务日志详解

    分析下MySql中innodb存储引擎是如何通过日志来实现事务的? Mysql会最大程度的使用缓存机制来提高数据库的访问效率,但是万一数据库发生断电,因为缓存的数据没有写入磁盘,导致缓存在内存中的数据 ...

  8. MySQL中InnoDB锁不住表的原因

    MySQL中InnoDB锁不住表是因为如下两个参数的设置: mysql> show variables like '%timeout%'; +-------------------------- ...

  9. mysql 中 innoDB 与 MySAM

    mysql 中 innoDB 与 MyISAM 的特点 --ENGINE = innodb 1.提供事务处理,支持行锁: 2.不加锁读取,增加并发读的用户数量和空间: 3. insert/update ...

随机推荐

  1. 第2章 Selenium2-java 测试环境搭建

    2.1  Window下环境搭建 2.1.1 安装Java 2.1.2 安装Eclipse (网上资源很多,就不详将了). 2.1.3 下载Java版的Selenium包. 下载地址:http://d ...

  2. java 操作 RabbitMQ 发送、接受消息

    例子1 Producer.java import java.io.IOException; import java.util.concurrent.TimeoutException; import c ...

  3. C# Web 数据注解Data Annotations、模型状态ModelState、数据验证

    C#中的模型状态与数据注解,为我们提供了很便利的请求数据的验证. 1. ModelState ModelState在进行数据验证的时候很有用的,它是: 1)验证数据,以及保存数据对应的错误信息. 2) ...

  4. MVC的部分视图(Partial View)

    MVC的部分视图确实与asp.net的用户控件有几分相似,实际应用起来的方式,它又是那样不尽相同. 上次练习了<MVC母版页_Layout.cshtml>http://www.cnblog ...

  5. Dapper入门使用,代替你的DbSQLhelper

    Dapper介绍 Dapper是.Net下的一个轻量级ORM框架.在小型工具向的项目下,使用Dapper会使数据库操作层代码更加优雅. Dapper的使用 在项目中使用引用Dapper非常简单,你可以 ...

  6. WPF备忘录(3)如何从 Datagrid 中获得单元格的内容与 使用值转换器进行绑定数据的转换IValueConverter

    一.如何从 Datagrid 中获得单元格的内容 DataGrid 属于一种 ItemsControl, 因此,它有 Items 属性并且用ItemContainer 封装它的 items. 但是,W ...

  7. SQLServer 里面的 DDL,DML,DCL,TCL

    1.DDL (Data Definition Language )数据库定义语言 statements are used to define the database structure or sch ...

  8. Unity主线程和子线程跳转调用(1)

    Unity除了一些基本的数据类型,几乎所有的API都不能在非unity线程中调用,如果项目中有一段很耗时操作,unity可能会出现“假死”.如果这段操作是和unity无关的,我们可以把这个耗时的操作放 ...

  9. Application作用域实现:当用户重复登录时,挤掉原来的用户

    Application作用域实现:当用户重复登录时,挤掉原来的用户 一.实现思想 1.application(ServletContext)是保存在服务器端的作用域,我们在application中保存 ...

  10. 封装7z软件实现批量文件或目录压缩

    哈哈,作为一个特别懒的运维人来说 兄弟我写了一个批量压缩文件或目录的小工具,用来批量压缩文件目录 弄一下,然后就不用管他了,后天看结果就好了 操作步骤: 1.选择想做压缩处理的根目录 2.选择你要的功 ...