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

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

作者头像
heidsoft
发布于 2023-03-18 09:43:31
发布于 2023-03-18 09:43:31
78300
代码可运行
举报
运行总次数: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
第7章_InnoDB数据存储结构
🧑个人简介:大家好,我是 shark-Gao,一个想要与大家共同进步的男人😉😉
程序员Leo
2023/08/02
2370
第7章_InnoDB数据存储结构
Oracle、MySQL、PG是如何处理数据库“半页写”的问题的?
数据库“断页”是个很有意思的话题,目前任何数据库应该都绕不过去。我们知道数据库的块大小一般是8k、16k、32k,而操作系统块大小是4k,那么在数据库刷内存中的数据页到磁盘上的时候,就有可能中途遭遇类似操作系统异常断电而导致数据页部分写的情况,进而造成数据块损坏,数据块损坏对于某些数据库是致命的,可能导致数据库无法启动。既然对于断页问题数据库都可能遇到,那么再来看看主流数据库是如何避免发生断页的。
数据库架构之美
2020/11/05
1.7K0
MYSQL 内存机制分析与监控
种数据库都有它自己的内存机制,如果说汽车的三大件,发动机,变速箱,底盘。数据库的内存机制算是数据库核心的核心,一个没有好的内存管理和分配的数据库,一定是不会有好的性能。
AustinDatabases
2019/06/21
2K0
MYSQL 内存机制分析与监控
关于MySQL极限值的初步验证纠错(二)
之前写了一篇自己的简单测试总结:关于MySQL极限值的初步验证纠错 今天在这个基础上继续做一些分析,如果说最权威,最全面的材料,那应该非官方文档莫属了,而要把文档看明白,理解清楚,那就只有大量的练习了,目前我是没发现捷径可走,如果有的话,请告知。 要想较为全面的了解MySQL中的极限值,或者叫做边界值,有很多需要考虑的点,我们有些可以做测试,有些就需要参考文档了。比如一个表里的列最多是1017个,注意这里是最多,如果是varchar型,那就达不到1017,但是最大值1017的结论还是成立的
jeanron100
2018/03/22
1K0
针对 MySQL/InnoDB 刷盘调优
这篇文章是讲述 InnoDB 刷盘策略系列文章的第三篇。本文主要讲述 性能调优。另外2篇文章参考
用户1278550
2022/07/30
2.2K0
深入浅出 InnoDB Flushing
作为MySQL InnoDB IO 调优系列的第二篇, 第一篇文章 参见Give Love to Your SSDs – Reduce innodb_io_capacity_max !
用户1278550
2022/07/30
1K0
深入浅出 InnoDB Flushing
InnoDB存储引擎之内存管理
在InnoDB存储引擎中,数据库中的缓冲池是通过LRU(Latest Recent Used,最近最少使用)算法来进行管理的,即最频繁使用的页在LRU列表的最前段,而最少使用的页在LRU列表的尾端,当缓冲池不能存放新读取到的页时,首先释放LRU列表尾端的页。
AsiaYe
2019/11/06
1K0
InnoDB存储引擎之内存管理
Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构
前面我们已经剖析了mysql中InnoDB与MyISAM索引的数据结构,了解了B+树的设计思想、原理,并且介绍了B+树与Hash结构、平衡二叉树、AVL树、B树等的区别和实际应用场景。
半旧518
2022/10/26
1.4K0
Mysql进阶索引篇02——InnoDB存储引擎的数据存储结构
数据库|基于内存的持久性
内存数据库系统在磁盘上维护备份,以提供持久性并防止易失性。有些数据库只在内存中存储数据,没有任何持久性保证。
heidsoft
2021/03/15
6680
数据库|基于内存的持久性
MySQL innodb_page_size
墨墨导读:Page是MySQL Innodb存储的最基本结构,也是Innodb磁盘管理的最小单位,了解page的一些特性,可以更容易理解MySQL。
数据和云
2020/12/08
2.4K0
MySQL innodb_page_size
敲黑板:InnoDB的Double Write,你必须知道
上一次我们讲过Insert Buffer 是用来提高存储引擎性能上的提升,Double Write 就是为了在数据库崩溃恢复时保证数据不丢失的一个重要特性,保证了数据的可靠性。
鲁大猿
2020/11/03
1.3K0
MySQL的内存结构与物理结构
MySQL的数据存储结构主要分两个方面:物理存储结构与内存存储结构,作为数据库,所有的数据最后一定要落到磁盘上,才能完成持久化的存储。内存结构为了实现提升数据库整体性能,主要用于存储临时数据和日志的缓冲。本文主要讲MySQL的物理结构,以及MySQL的内存结构,对于存储引擎也主要以InnoDB为主。
搬砖俱乐部
2019/08/30
8.4K0
关系型数据库 MySQL 之 InnoDB 体系结构
InnoDB 存储引擎是 MySQL 5.5 版本后的默认存储引擎,支持事务 ACID,回滚,系统崩溃恢复能力及多版本并发控制的事务安全,主要用于 OLTP 数据库业务场景;支持自增长列(auto_increment);支持外键约束(foreign key);支持 MVCC 的行级锁;使用 Btree 索引;如果你还没有看到前面一文介绍 MySQL 体系结构,那么推荐戳此查看[MySQL 体系结构详解],介绍完 MySQL 体系结构,下面来一起学习 InnoDB 体系结构。
JiekeXu之路
2019/08/15
1.4K0
MySQL索引原理揭秘:构建高效数据库的核心技术
开始之前推荐一篇实用的文章:《MySQL存储引擎大厂面试经典三连问》,作者:【小白的大数据之旅】。
Lion 莱恩呀
2024/11/27
2290
MySQL索引原理揭秘:构建高效数据库的核心技术
MySQL InnoDB 行记录存储结构
工作中我们基本上都是用MySQL的InnoDB存储引擎,但是大家有去了解过它的底层存储结构吗,想必绝大部分人不知道,或者说不知道怎么查相关知识,刚好来看这篇文章就对了!
小许code
2023/05/15
9530
MySQL InnoDB 行记录存储结构
程序员必备的数据库知识:数据存储结构
数据在数据库中的存储方式就是数据存储结构。传统数据库由上到下,可以分为网络接入层、计算引擎层、存储引擎层、系统文件层,数据存储结构就是在存储引擎层,数据库通过存储引擎实现CRUD操作。不同的存储引擎决定了数据库的性能和功能,所以存储引擎层是数据库的核心。另外,在数据库中数据是以表的形式存储,所以存储引擎也可以称为表类型。
NineData
2023/02/03
1.8K0
程序员必备的数据库知识:数据存储结构
【MySQL系列】- 浅入Buffer Pool
InnoDB 存储引擎是以数据页为单位来管理存储空间的。InnoDB 存储引擎在处理客户端的请求时,当需要访问某个数据页的数据时,就会把完整的数据页的数据全部加载到内存中,也就是说即使我们只需要访问一个数据页的一条记录,那也需要先把整个数据页的数据加载到内存中。将整个数据页加载到内存中后就可以进行读写访问了,在进行完读写访问之后并不着急把该数据页对应的内存空间释放掉,而是将其缓存起来,这样将来有请求再次访问该页面时,就可以省去磁盘 IO 的开销了。这个缓存就称之为Buffer Pool。
索码理
2022/09/20
9280
【MySQL系列】- 浅入Buffer Pool
MySQL InnoDB 存储结构
由上图可以看出,tablespace由segment组成,segment由extend组成,extend由page组成,page由row组成 在MySQL中默认会有一个共享表空间ibdata1,如果设置了innodb_file_per_table=on时,每张表内的数据放在各自的tablespace中,私有tablespace仅包括数据,索引,插入缓冲Bitmap页,而其他的例如回滚信息,插入缓冲索引页,系统事务信息,二次写缓冲等都还是放在共享表空间
yingzi_code
2019/08/31
1.6K0
MySQL提升笔记(4)InnoDB存储结构
这一节本来计划开始索引的学习,但是在InnoDB存储引擎的索引里,存在一些数据存储结构的概念,这一节先了解一下InnodDB的逻辑存储结构,为索引的学习打好基础。
三分恶
2021/04/22
7390
相关推荐
MySQL InnoDB 存储引擎原理浅析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验