---
title: 'Mysql InnoDB引擎的索引和存储结构'
pubDate: 2019-01-20
tags:
  - 'others'
description: 'Mysql InnoDB引擎的索引和存储结构'
---

在Oracle 和SQL Server等数据库中只有一种存储引擎，所有数据存储管理机制都是一样的。

而MySql数据库提供了多种存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎，用户也可以根据自己的需要编写自己的存储引擎。

## MySQL主要存储引擎的区别

MySQL默认的存储引擎是MyISAM，其他常用的就是InnoDB，另外还有MERGE、MEMORY(HEAP)等。

### 主要的几个存储引擎

MyISAM管理非事务表，提供高速存储和检索，以及全文搜索能力。

MyISAM是Mysql的默认存储引擎。当create创建新表时，未指定新表的存储引擎时，默认使用MyISAM。每个MyISAM在磁盘上存储成三个文件。文件名都和表名相同，扩展名分别是.frm（存储表定义）、.MYD (MYData，存储数据)、.MYI (MYIndex，存储索引)。数据文件和索引文件可以放置在不同的目录，平均分布io，获得更快的速度。

InnoDB存储引擎用于事务处理应用程序，具有众多特性，包括ACID事务支持，提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比MyISAM存储引擎，InnoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引。

Memory将所有数据保存在内存中，可以应用于临时表中在需要快速查找引用和其他类似数据的环境下，可提供极快的访问。Memory使用哈希索引，所以数据的存取速度非常快。

Merge允许MySQL DBA或开发人员将一系列等同的MyISAM表以逻辑方式组合在一起，并作为1个对象引用它们。对于诸如数据仓储等VLDB环境十分适合。

### 不同存储引擎的横向对比

| 特点           | MyISAM | BDB  | Memory | InnoDB |
| -------------- | ------ | ---- | ------ | ------ |
| 存储限制       | x      | x    | v      | 64TB   |
| 事务安全       |        | v    |        | v      |
| 锁机制         | 表锁   | 页锁 | 表锁   | 行锁   |
| B树索引        | v      | v    | v      | v      |
| 哈希索引       |        |      | v      | v      |
| 全文索引       | v      |      |        |        |
| 集群索引       |        |      |        | v      |
| 数据缓存       |        |      | v      | v      |
| 索引缓存       | v      |      | v      | v      |
| 数据可压缩     | v      |      |        |        |
| 空间使用       | 低     | 低   |        | 高     |
| 内存使用       | 低     | 低   | 中     | 高     |
| 批量插入的速度 | 高     | 高   | 高     | 低     |
| 支持外键       |        |      |        | v      |

### 查看和配置存储引擎的操作

#### 1.用show engines; 命令可以显示当前数据库支持的存储引擎情况；

#### 2.要查看表的定义结构等信息可以使用以下几种命令：

```
Desc[ribe] tablename; //查看数据表的结构
Show create table tablename; //显示表的创建语句，可以查看创建表时指定的ENGINE
show table status like ‘tablename’\G显示表的当前状态值
```

#### 3.设置或修改表的存储引擎

创建数据库表时设置存储存储引擎的基本语法是：

```
Create table tableName(
columnName(列名1) type(数据类型) attri(属性设置),
columnName(列名2) type(数据类型) attri(属性设置),
……..) engine = engineName
```

修改存储引擎，可以用命令

```
Alter table tableName engine =engineName
```

对于整个服务器或方案，你并不一定要使用相同的存储引擎，可以为方案中的每个表使用不同的存储引擎。

## InnoDB的存储结构

InnoDB使用页面存储结构，下面是InnoDB的表空间结构图：

![](https://source.mkshell.com/15479681638675.jpg)

Page页面存储格式如下图所示：

![](https://source.mkshell.com/15479681741263.jpg)

一个页面的存储由以下几部分组成：

1. 页头（Page Header）：记录页面的控制信息，共占150字节，包括页的左右兄弟页面指针、页面空间使用情况等，页头的详细说明会在下一篇中描述。
2. 最小虚记录、最大虚记录：两个固定位置存储的虚记录，本身并不存储数据。最小虚记录比任何记录都小，而最大虚记录比任何记录都大。
3. 记录堆（record heap）：指上图的橙黄色部分。表示页面已分配的记录空间，也是索引数据的真正存储区域。记录堆分为两种，即有效记录和已删除记录。有效记录就是索引正常使用的记录，而已删除记录表示索引已经删除，不在使用的记录，如上图的深蓝色部分。随着记录的更新和删除越来越频繁，记录堆中已删除记录将会越多，即会出现越来越多的空洞（碎片）。这些已删除记录连接起来，就会成为页面的自由空间链表。
4. 未分配空间：指页面未使用的存储空间，随着页面不断使用，未分配空间将会越来越小。当新插入一条记录时，首先尝试从自由空间链表中获得合适的存储位置（空间足够），如果没有满足的，就会在未分配空间中申请。
5. slot区：slot是一些页面有效记录的指针，每个slot占两个字节，存储了记录相对页面首地址的偏移。如果页面有n条有效记录，那么slot的数量就在n/8+2~n/4+2之间。下一节详细介绍slot区，它是记录页面有序和二分查找的关键。
6. 页尾（Page Tailer）：页面最后部分，占8个字节，主要存储页面的校验信息。

页面中的页头，最大/最小虚记录以及页尾都是页面中有固定的存储位置。

## InnoDB的索引结构

InnoDB使用B+Tree的方式存储索引。

Innodb的一个表可能包含多个索引，每个索引都使用B+树来存储。而索引包括聚集索引和二级索引，聚集索引使用表的主键作为索引键，包含表的所有字段。二级索引只包含索引键和聚集索引键（主键）的内容，不包括其他字段。每一个索引都是一棵B+树，每棵B+树由很多页面组成，而每个页面大小一般为16K。从B+树的组织结构来看，B树的页面可分为：

叶子节点：B树层次为0的页面，存储记录的所有内容。 非叶子节点：B树层次大于0的页面，只存储索引键和页面指针。

一棵典型的B+树结构：

![](https://source.mkshell.com/15479682010568.jpg)

从上图可知，相同层次的页面是用一个双向链表连接起来的。 一般情况下，从B+树的最左边叶子节点开始，一直向右扫描，就可以得到B+树的从小到大的所有数据。因此，对于叶子节点，有如下特征： 页内数据是按索引键排序的。 页面的任一记录的索引键值不小于其左兄弟页面的任何记录。

参考文章：[https://yq.aliyun.com/articles/24249](https://yq.aliyun.com/articles/24249)

原文链接：[http://www.cnblogs.com/binyue/p/4135121.html](http://www.cnblogs.com/binyue/p/4135121.html)
