null值在InnoDB中的存储及索引优化

前言

通过阅读本文你可以了解下面几个问题:

  1. 对于null值在mysql中具体是怎么存储的
  2. null可以使用到索引吗

NULL的存储

准确的来说mysql的数据存储都是底层存储引擎的工作,所以这个问题取决于你使用的存储引擎,这里参考Stack Overflow上面的一篇解答。

MyISAM存储引擎

Myisam的每一条记录都会有一个记录头(record header),其中若干个比特位来标识字段是否为null。

具体内容如下:

  1. "X bit" = 0 if row is deleted, = 1 if row is not deleted
  2. "Null Bits" = 1 if row contains any null fields, or = 0 otherwise.
  3. "Filler Bits" = 1

记录头的总长度为:(1 + number of NULL columns + 7) / 8 bytes

对于myisam即使字段为null,也会占据存储空间。

由于现在广泛使用的都是InnoDB存储引擎,所以这里不过多展开。原文请参考官方文档:dev.mysql.com/doc/interna…

InnoDB存储引擎

首先我们要知道InnoDB里面的数据存储分为聚簇索引(主键索引)树与非聚簇索引(二级索引),同时InnoDB都是以页为单位进行读写的,下面对于聚簇索引的页子结点我们称之为数据页,里面存储的是一行行数据,对于二级索引的叶子节点我们称之为索引页,里面存储的是一行行索引记录(索引值+主键值)。

对于InnoDB的null如何存储取决于InnoDB 表的Row Formats配置,对于MySQL 5.0.3 到 MySQL 5.7.8默认的row format都是COMPACT

5.7.9以及8.0默认都是DYNAMIC

use information_schema; -- 切换到mysql内置的元数据管理数据库

SELECT * FROM TABLES WHERE TABLE_SCHEMA = 'databaseName' and TABLE_NAME = 'tableName'\G; -- 查看表的row format配置
复制代码

DYNAMIC与COMPACT类似,只是提供了一些增强,参考至官方文档

扫描二维码关注公众号,回复: 13171851 查看本文章

The DYNAMIC row format offers the same storage characteristics as the COMPACT row format but adds enhanced storage capabilities for long variable-length columns and supports large index key prefixes.

对于COMPACT row format来说,其会在每一行记录前专门有若干个比特位来标识字段是否为空。这些比特位占据 CEILING(N / 8) 个字节,其中N为nullable列的个数。对于非空列当然则不需要比特位来标识null与否。

更加详细的关于COMPACT的存储结构的介绍,可以参考这篇博客:blog.jcole.us/2013/01/10/… format。

Null是否可以使用到索引

在MySQL官方文档(5.7版本8.0版本)中明确说明is null可以进行与等值查询一样的优化。

参考文档

猜你喜欢

转载自juejin.im/post/7031170824845557796
今日推荐