Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >数据库|数据存储结构深入

数据库|数据存储结构深入

作者头像
heidsoft
发布于 2023-03-18 09:43:31
发布于 2023-03-18 09:43:31
80300
代码可运行
举报
运行总次数:0
代码可运行

存储蓝图

database > tablespaces > pages > rows > columns

物理存储

逻辑存储结构

The storage structure of InnoDB page Page type

  • Data page (B-tree node)
  • Undo page (undo log page)
  • System page
  • Transaction data page (transaction system page)
  • Insert buffer bitmap page (insert buffer page)
  • Uncompressd BLOB page
  • Compressed BLOB page

页结构

why innodb index length limit to 3072 when page_size is 16k?

An InnoDB page must store >= 2 keys; a secondary key record must also contain the primary key value. Therefore, if both the primary key and the secondary key are at this maximum length, it must be less than 1/4th of the free space on a page including record overhead.

MySQL imposes its own limit to this number; MAX_KEY_LENGTH = 3072.

For page sizes = 16k, InnoDB historically reported 3500 bytes here, But the MySQL limit of 3072 was always used through the handler interface.

一个 InnoDB 页面必须存储 >= 2 个键;辅助键记录还必须包含主键值。因此,如果主键和辅助键都处于此最大长度,则它必须小于页面上可用空间的 1/4,包括记录开销。MySQL 对此数字施加了自己的限制;最大键长度 = 3072。对于页面大小 = 16k,InnoDB 历史上在这里报告 3500 字节,但是 3072 的 MySQL 限制始终通过处理程序接口使用。

https://github.com/mysql/mysql-server/blob/8.0/storage/innobase/handler/ha_innodb.cc#L6380-L6401

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/** Returns the maximum number of keys.
 @return MAX_KEY */

uint ha_innobase::max_supported_keys() const { return (MAX_KEY); }

/** Returns the maximum key length.
 @return maximum supported key length, in bytes */

uint ha_innobase::max_supported_key_length() const {
  /* An InnoDB page must store >= 2 keys; a secondary key record
  must also contain the primary key value.  Therefore, if both
  the primary key and the secondary key are at this maximum length,
  it must be less than 1/4th of the free space on a page including
  record overhead.
  MySQL imposes its own limit to this number; MAX_KEY_LENGTH = 3072.
  For page sizes = 16k, InnoDB historically reported 3500 bytes here,
  But the MySQL limit of 3072 was always used through the handler
  interface. */

https://github.com/mysql/mysql-server/blob/8.0/sql/sql_const.h#L47

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
constexpr const unsigned int MAX_KEY{MAX_INDEXES}; /* Max used keys */
constexpr const unsigned int MAX_REF_PARTS{16};    /* Max parts used as ref */
constexpr const unsigned int MAX_KEY_LENGTH{3072}; /* max possible key */

InnoDB is full of compromises between speed and space.

InnoDB was designed before SSDs, so reading multiple adjacent disk sectors was a good idea, especially if you are likely to need more than just one piece of the 16KB block.

If you look at the disk usage for the entire database, you may find a "waste" of only a few percent when measuring space.

Also, today, most applications are small enough to fit entirely in RAM. So, the block size makes little difference. Actually, 16KB blocks is slightly faster on the initial load due to fewer I/Os, even for SSDs.

If you have a huge dataset and are I/O-bound you may get into performance difficulties if you mostly do random reads of one small row. Example: key-value dataset with UUIDs for ids. In this one use case, a smaller block size on SSDs might be noticeably faster.

Back to tradeoffs -- That UUID (etc) example is not very common.

InnoDB 在速度和空间之间充满了妥协。InnoDB 是在 SSD 之前设计的,因此读取多个相邻磁盘扇区是一个好主意,尤其是当您可能需要 16KB 块的多个部分时。如果您查看整个数据库的磁盘使用情况,您可能会发现在测量空间时只有百分之几的“浪费”。此外,今天,大多数应用程序都足够小,可以完全放入 RAM 中。因此,块大小几乎没有区别。实际上,由于 I/O 较少,16KB 块在初始加载时稍微快一些,即使对于 SSD 也是如此。如果你有一个巨大的数据集并且受 I/O 限制,如果你主要对一小行进行随机读取,你可能会遇到性能困难。示例:具有用于 ID 的 UUID 的键值数据集。在这个用例中,SSD 上较小的块大小可能会明显更快。回到权衡——UUID(等)示例不是很常见。

InnoDB requires that at least two rows fit in a given page. This rule is bent a bit because the variable-length data types VARCHAR, VARBINARY, TEXT, and BLOB may overflow to additional pages. Both otherwise, a given row must fit within a little less than 8KB.

If the InnoDB page size were smaller than the current default of 16KB, the size limit of a row would be lower than it currently is. In fact, you can reconfigure InnoDB to use different page sizes, and this does change the maximum row size.

The default of 16KB is considered appropriate for most cases. It's true that there's a chance it does not align with the disk sector size exactly, but hopefully when performance is crucial your queries read from the buffer pool, not from disk.

InnoDB 要求至少两行适合给定页面。这条规则有点弯曲,因为可变长度数据类型 VARCHAR、VARBINARY、TEXT 和 BLOB 可能会溢出到其他页面。否则,给定行的大小必须小于 8KB。如果 InnoDB 页面大小小于当前默认值 16KB,则行的大小限制将低于当前值。事实上,您可以重新配置 InnoDB 以使用不同的页面大小,这确实会改变最大行大小。16KB 的默认值被认为适用于大多数情况。的确,它有可能与磁盘扇区大小不完全一致,但希望当性能至关重要时,您的查询是从缓冲池中读取的,而不是从磁盘中读取的。

内存

内存数据库系统在磁盘上维护备份,以提供持久性并防止易失性。有些数据库只在内存中存储数据,没有任何持久性保证。

数据库在认定操作完成之前,必须先将其结果写入一个顺序日志文件。为了避免在启动过程中或奔溃后重放完整的日志内容,内存数据库维护了一个备份副本。该备份副本使用一个基于磁盘且已排序的数据结构。并且对该结构的修改通常是异步(与客户端请求解耦)且分批处理的。这样可以减少I/O操作数量。在恢复过程中,数据库可以从备份和日志还原数据库内容

日志数据通常用于批量备份,在处理该批日志数据之后,备份将持有截止到这一特定时间点的数据库快照。因此可以丢弃之前的日志内容。这个过程称为生成检查点(checkpointing). 它会更新磁盘上点数据库快照使其更接近最新的日志条目,从而缩短恢复时间,且备份过程不会阻塞客户端请求。

使用页缓存在内存里,序列化格式和数据布局也会使磁盘数据库产生额外的开销,而不会达到与内存数据库相同的优化程序

pagecache

Page Cache的机制如上图所示,具体来说,当应用程序读文件时,系统先检查读取的文件页是否在缓存中;如果在,直接读出即可;如果不在,就将其从磁盘中读入缓存,再读出。此时如果内存有足够的内存空间,该页可以在page cache中驻留,其他进程再访问该部分数据时,就不需要访问磁盘了。

同样,在写文件之前,系统先检查对应的页是否已经在缓存中;如果在,就直接将数据写入page cache,使其成为脏页(drity page)等待刷盘;如果不在,就在缓存中新增一个页面并写入数据(这一页面也是脏页)。真正的磁盘I/O会由操作系统调用fsync等方法来实现,这一调用可以是异步的,保证磁盘I/O不影响文件读写的效率。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
dirty_background_ratio
// 触发文件系统异步刷脏的脏页占总可用内存的最高百分比,当脏页占总可用内存的比例超过该值,后台回写进程被触发进行异步刷脏。

dirty_ratio
// 触发文件系统同步刷脏的脏页占总可用内存的最高百分比,当脏页占总可用内存的比例超过该值,生成新的写文件操作的进程会先执行刷脏。

dirty_background_bytes & dirty_bytes
// 上述两种刷脏条件还可通过设置最高字节数而非比例触发。如果设置bytes版本,则ratio版本将变为0,反之亦然。

dirty_expire_centisecs
// 这个参数指定了脏页多长时间后会被周期性刷脏。下次周期性刷脏时,脏页存活时间超过该值的页面都将被刷入磁盘。

dirty_writeback_centisecs 
// 这个参数指定了多长时间唤醒一次刷脏进程,检查缓存并刷下所有可以刷脏的页面。该参数设为零内核会暂停周期性刷脏。
  • http://mysql.taobao.org/monthly/2020/09/01/
  • https://lwn.net/ml/linux-fsdevel/20191210162454.8608-1-axboe@kernel.dk/
  • https://web.cs.iastate.edu/~prabhu/Tutorial/title.html
  • http://www.howardhuang.us/teaching/cs232/24-Cache-writes-and-examples.pdf
  • https://man7.org/tlpi/code/online/dist/filebuff/direct_read.c.html
  • https://linux.die.net/man/2/open
  • https://www.alibabacloud.com/forum/read-446
  • https://stackoverflow.com/questions/73382682/why-innodb-index-length-limit-to-3072-when-page-size-is-16k
  • https://dev.mysql.com/blog-archive/innodb-tablespace-space-management/
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-02-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云数智圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MySQL InnoDB 存储引擎原理浅析
本文主要基于MySQL 5.6以后版本编写,多数知识来着书籍《MySQL技术内幕++InnoDB存储引擎》,今年的多数学习知识只写在笔记里,较为零散,最近稍有时间整理出来,分享进步。
程序员小强
2021/05/27
1.6K0
关系型数据库 MySQL 之 InnoDB 体系结构
InnoDB 存储引擎是 MySQL 5.5 版本后的默认存储引擎,支持事务 ACID,回滚,系统崩溃恢复能力及多版本并发控制的事务安全,主要用于 OLTP 数据库业务场景;支持自增长列(auto_increment);支持外键约束(foreign key);支持 MVCC 的行级锁;使用 Btree 索引;如果你还没有看到前面一文介绍 MySQL 体系结构,那么推荐戳此查看[MySQL 体系结构详解],介绍完 MySQL 体系结构,下面来一起学习 InnoDB 体系结构。
JiekeXu之路
2019/08/15
1.4K0
Oracle、MySQL、PG是如何处理数据库“半页写”的问题的?
数据库“断页”是个很有意思的话题,目前任何数据库应该都绕不过去。我们知道数据库的块大小一般是8k、16k、32k,而操作系统块大小是4k,那么在数据库刷内存中的数据页到磁盘上的时候,就有可能中途遭遇类似操作系统异常断电而导致数据页部分写的情况,进而造成数据块损坏,数据块损坏对于某些数据库是致命的,可能导致数据库无法启动。既然对于断页问题数据库都可能遇到,那么再来看看主流数据库是如何避免发生断页的。
数据库架构之美
2020/11/05
1.8K0
MySQL提升笔记(4)InnoDB存储结构
这一节本来计划开始索引的学习,但是在InnoDB存储引擎的索引里,存在一些数据存储结构的概念,这一节先了解一下InnodDB的逻辑存储结构,为索引的学习打好基础。
三分恶
2021/04/22
7480
第7章_InnoDB数据存储结构
🧑个人简介:大家好,我是 shark-Gao,一个想要与大家共同进步的男人😉😉
程序员Leo
2023/08/02
2490
第7章_InnoDB数据存储结构
MySQL四:InnoDB的存储结构
「MySQL存储引擎最大的特点就是【插件化】,可以根据自己的需求使用不同的存储引擎,innodb存储引擎支持行级锁以及事务特性,也是多种场合使用较多的存储引擎。」
云扬四海
2022/09/26
9770
MySQL innodb_page_size
墨墨导读:Page是MySQL Innodb存储的最基本结构,也是Innodb磁盘管理的最小单位,了解page的一些特性,可以更容易理解MySQL。
数据和云
2020/12/08
2.5K0
MySQL innodb_page_size
【MySQL经典案例分析】关于数据行溢出由浅至深的探讨
故事的开头我们先来看一个常见的sql报错信息, 相信对于这类报错大家一定遇到过很多次了...
迪B哥
2018/12/20
3K3
Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构
前面我们已经剖析了mysql中InnoDB与MyISAM索引的数据结构,了解了B+树的设计思想、原理,并且介绍了B+树与Hash结构、平衡二叉树、AVL树、B树等的区别和实际应用场景。
半旧518
2022/10/26
1.4K0
Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构
Innodb是如何运转的
Master Thread是非常核心的后台线程,主要负责脏页的刷新,合并插入缓冲,UNDO页回收等。
大忽悠爱学习
2022/12/07
4180
Innodb是如何运转的
MySQL 存储引擎 - InnoDB 实现原理介绍
内存结构主要包括 Buffer Pool、Change Buffer、Adaptive Hash Index和 Log Buffer 四大组件
一个会写诗的程序员
2023/03/08
1.2K1
MySQL 存储引擎 - InnoDB 实现原理介绍
程序员必备的数据库知识:数据存储结构
数据在数据库中的存储方式就是数据存储结构。传统数据库由上到下,可以分为网络接入层、计算引擎层、存储引擎层、系统文件层,数据存储结构就是在存储引擎层,数据库通过存储引擎实现CRUD操作。不同的存储引擎决定了数据库的性能和功能,所以存储引擎层是数据库的核心。另外,在数据库中数据是以表的形式存储,所以存储引擎也可以称为表类型。
NineData
2023/02/03
1.8K0
程序员必备的数据库知识:数据存储结构
InnoDB存储引擎之内存管理
在InnoDB存储引擎中,数据库中的缓冲池是通过LRU(Latest Recent Used,最近最少使用)算法来进行管理的,即最频繁使用的页在LRU列表的最前段,而最少使用的页在LRU列表的尾端,当缓冲池不能存放新读取到的页时,首先释放LRU列表尾端的页。
AsiaYe
2019/11/06
1K0
InnoDB存储引擎之内存管理
深入浅出 InnoDB Flushing
作为MySQL InnoDB IO 调优系列的第二篇, 第一篇文章 参见Give Love to Your SSDs – Reduce innodb_io_capacity_max !
用户1278550
2022/07/30
1K0
深入浅出 InnoDB Flushing
MYSQL INNODB表压缩
压缩前提 表压缩能提升性能,减少存储空间,主要是用在字符类型比较大的表上(VARCHAR,VARBINARY和BLOB和TEXT类型),且读多写少的情况下,如果你的应用是io密集型的,不是cpu密集型的,那么压缩会带来很多性能的提升,例如:数据仓库。 innodb_file_format = Barracuda --模式支持压缩 innodb_file_per_table = on --必须是独立表空间 压缩原理 InnoDB支持两种文件格式 Antelope(羚羊)和Barracuda(梭鱼): Ante
MySQL轻松学
2018/03/09
9.9K0
MYSQL INNODB表压缩
MySQL的内存结构与物理结构
MySQL的数据存储结构主要分两个方面:物理存储结构与内存存储结构,作为数据库,所有的数据最后一定要落到磁盘上,才能完成持久化的存储。内存结构为了实现提升数据库整体性能,主要用于存储临时数据和日志的缓冲。本文主要讲MySQL的物理结构,以及MySQL的内存结构,对于存储引擎也主要以InnoDB为主。
搬砖俱乐部
2019/08/30
8.5K0
MySQL 如何高效可靠处理持久化数据
需要注意的是,连接操作比较耗资源,所以一般使用长连接,不过长连接有内存占用的问题。解决方案定时断开或者在大查询之后断开重连(5.7之后可以调用 MySQL_reset_connection(),在不断开的情况下释放资源)
阿珍
2025/07/30
1270
MySQL 如何高效可靠处理持久化数据
数据库|基于内存的持久性
内存数据库系统在磁盘上维护备份,以提供持久性并防止易失性。有些数据库只在内存中存储数据,没有任何持久性保证。
heidsoft
2021/03/15
6780
数据库|基于内存的持久性
【MySQL系列】- 浅入Buffer Pool
InnoDB 存储引擎是以数据页为单位来管理存储空间的。InnoDB 存储引擎在处理客户端的请求时,当需要访问某个数据页的数据时,就会把完整的数据页的数据全部加载到内存中,也就是说即使我们只需要访问一个数据页的一条记录,那也需要先把整个数据页的数据加载到内存中。将整个数据页加载到内存中后就可以进行读写访问了,在进行完读写访问之后并不着急把该数据页对应的内存空间释放掉,而是将其缓存起来,这样将来有请求再次访问该页面时,就可以省去磁盘 IO 的开销了。这个缓存就称之为Buffer Pool。
索码理
2022/09/20
9490
【MySQL系列】- 浅入Buffer Pool
针对 MySQL/InnoDB 刷盘调优
这篇文章是讲述 InnoDB 刷盘策略系列文章的第三篇。本文主要讲述 性能调优。另外2篇文章参考
用户1278550
2022/07/30
2.2K0
相关推荐
MySQL InnoDB 存储引擎原理浅析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验