程序员必备的数据库知识:数据存储结构

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 本文介绍了五种常见数据存储结构,另外还有图、表格、链式、R-TREE等数据结构并未涉及,当然本文也只是对数据库存储结构的知识抛砖引玉,有兴趣的同学可以对每一种数据存储结构做更详细和深入的学习。司马辽太杰是 NineData 工程师。NineData 向企业和个人提供高效、安全的数据库SQL开发、数据库备份、数据复制/迁移/集成、数据对比等功能,是一个SaaS服务开箱即用,可以快速提升企业SQL开发效率,保障企业数据安全。NineData 官网地址:https://ninedata.cloud

一、前言

数据在数据库中的存储方式就是数据存储结构。传统数据库由上到下,可以分为网络接入层、计算引擎层、存储引擎层、系统文件层,数据存储结构就是在存储引擎层,数据库通过存储引擎实现CRUD操作。不同的存储引擎决定了数据库的性能和功能,所以存储引擎层是数据库的核心。另外,在数据库中数据是以表的形式存储,所以存储引擎也可以称为表类型。


本文将介绍,HEAP、B+TREE、COLUMN-STORE、 LSM-TREE、HASH等存储结构,这些不同的数据存储结构,导致不同数据库的索引、锁、事务等功能特性不同。下图是MySQL架构图,其中存储引擎有InnoDB、MyISAM、NDB Cluster、Memory等。

image.png

高性能MySQL架构

二、逻辑结构

在介绍数据存储结构前,需要先了解数据库逻辑存储架构,常见关系型数据库逻辑架构单元从小到大是:块(block,MySQL称为page 页) > 区(extent) > 段(segment) > 表空间(tablespace)。


块是数据库存储的最小单元,也是最小逻辑存储结构。不同数据库块的默认大小不一样,MySQL是16k,Oracle是8k。当数据写入块中,如果一条数据过大,就会连续占用几个块。块和块之间并不一定在物理上相连,只是在逻辑上使用双向链表关联,它们之间的物理位置有可能很远,所以数据库一般不以块作为最小的存储分配单位。


区(extent)是由一个或多个连续的块组成,区是Oracle和MySQL数据库的最小分配单位。段(segment)是由一个或多个区组成。它可以是连续的,也可以不连续。它是一个独立的逻辑结构,是存储对象、表、索引的数据对象,一个段属于一个数据对象,每创建一个新的的数据对象,就会创建新的独立段。不同类型的数据对象有不同的段:数据段、索引段、回滚段、临时段。


表空间(tablespace)是逻辑结构最高一级,数据库由一个或多个表空间组成,一个表空间则对应着一个或多个物理的数据文件,常用的表空间有数据表空间、索引表空间、系统表空间、日志表空间。下图是MySQL InnoDB逻辑存储架构图。

image (1).png

《MySQL 技术内幕 InnoDB存储引擎》

说明:如果表只存储了一条数据,那数据库也是要扫描整个最小存储单元(Oracle是block、MySQL是page)。这样设计是为了提高效率,因为物理I/O成本很大,不可能读、写一行数据就只扫描那行数据的磁盘。


三、HEAP

Heap表,也就是堆表,是Oracle数据库最常见、也是默认的表类型。堆表的数据会以堆的方式管理,意味着它的数据存取是随机的。数据库写数据时,会找到能放下此数据的合适空间。从表中删除数据时,则允许以后的写入和更新重用这部分空间。


比如先插入一个小行,接着插入一个大行,而且这个大行无法和小行无法存储在同一个块上,接着又插入一个小行。查询这三行数据它的默认排序是:小行、小行、大行。这些行并不按插入的顺序显示的,Oracle会找到能放下此数据的合适空间,而不是按照时间或者事务的某种顺序来存放。


堆表的特点是数据存储在表中,索引存储在索引里,这两者分开的。数据在堆中是无序的,索引让键值有序,但数据还是无序的。堆表中主键索引和普通索引一样的,都是存放指向堆表中数据的指针。


四、B+TREE

MySQL InnoDB 引擎将数据划分为若干页(page),以页作为磁盘与内存交互的基本单位,页默认的大小为16KB。这样每次磁盘IO至少读取一页数据到内存中或者将内存中一页数据写入磁盘,通过这种方式减少内存与磁盘的交互次数,从而提升性能。page的格式如下图:

image (2).png

《MySQL 技术内幕 InnoDB存储引擎》

MySQL InnoDB 引擎是使用B+Tree,B+Tree的特性是主键索引(又称聚集索引)的叶子节点保存的是真正的数据,而辅助索引(又称二级索引、非聚集索引)叶子节点的数据保存的是通过指向主键索引然后获得数据(也就是只根据辅助索引查询,需要进行一次回表)。

image (3).png


五、CLOUMN-STORE

传统的在线业务系统(OLTP)一般是以行存的方式,因为一行一行的写入读取符合在线业务场景。在联机分析处理系统(OLAP)中,常常需要统计分析某些列的数据,并对其进行分组、聚合运算,此时使用列存将会更高效。因为这样可以避免读取到不需要的列数据,另外同一列中的数据类型存储在一起也十分适合压缩,从而一个块可以存储更多的数据。

Apache Parquet是面向分析型业务的列式存储格式,一个Parquet文件的内容有Header、Data Block和Footer三部分组成。其中Data Block是具体存放数据的区域,它由多个Row Group(行组)组成,每个Row Group包含了一批数据。在Row Group中,数据按列汇集存放,每列的所有数据组合成一个Column Chunk(列块),一个列块具有相同的数据类型,不同的列块可以使用不同的压缩。因此一个Row Group由多个Column Chunk组成,Column Chunk的个数等于列数。每个Column Chunk中,数据按照Page为最小单元来存储,根据内容分为Data Page和Index Page。如下图。

image (4).png

Parquet文件内容

六、LSM-TREE

Google 的三驾马车之一 BigTable,这篇论文提到 LSM(Log-Structured-Merge-Tree 日志结构合并树)数据结构。这之后 LSM 被多个数据库作为存储结构,比如 HBase、TIDB、Oceabase,以及MySQL 的MyRocks存储引擎。简单说LSM是一种磁盘严格顺序写入、数据分level存储、每level的数据都按主键(Key)排序后存储、各level中的数据会定期merge然后写入下一level等特性的数据结构。


我们知道顺序写的性能比随机写性能好很多,通过顺序写替代随机写,提升数据库性能是常见的方法之一,比如WAL技术。LSM 的数据数据写入是日志式的(append only)顺序写入,写入数据时直接追加一条新记录。


当进行写数据时。先写入 Memtable 和预写日志(Write Ahead Logging, WAL)。因为Memtable 是内存操作,防止掉电需要将记录写入磁盘中的 WAL 保证数据不会丢失。当 MemTable 写满后会被转换为不可修改的 Immutable MemTable,并创建一个新的空 MemTable。后台线程会将 Immutable MemTable 写入到磁盘中形成一个新的 SSTable 文件,并随后销毁 Immutable MemTable。


SSTable (Sorted String Table) 是 LSM 树中在持久化存储的数据结构,它是一个有序的键值对文件。LSM 不会修改已存在的 SSTable,LSM 在修改数据时会直接在 MemTable 中写入新版本的数据,并等待 MemTable 落盘形成新的 SSTable。这样保证在同一个 SSTable 中 key 不会重复,但是不同的 SSTable 中还是会存在相同的 Key。


当读取数据时。因为最新的数据总是先写入 MemTable,所以在读取数据时首先要读取 MemTable 然后从新到旧搜索 SSTable,找到某个 key 第一个版本就是其最新版本。我们知道,刚写入的数据是很有可能被马上读取的,因此MemTable 还起到了很好的缓存作用。如下图。

image (5).png

Log-Structured-Merge-Tree 日志结构合并树

随着不断的写入 SSTable 数量会越来越多,数据库持有的文件句柄(FD)会越来越多,读取数据时需要搜索的 SSTable 也会越来越多。另一方面对于某个 Key 而言只有最新版本的数据是有效的,其它记录都是在白白浪费磁盘空间。因此对 SSTable 进行合并和压缩(Compact)就十分重要。在合并和压缩的过程中,会遇到读放大、写放大、空间放大等问题,这些不同的问题需要做取舍,也就诞生了多种合并压缩策略。


七、HASH

Redis HASH 是字符串字段和值之间关系的映射表,适合用于存储对象。比如:一个用户有多个属性字段,如:姓名、年龄、性别等等。

image (6).png

Redis HASH

如上图,左边是 Key 对应右边存储空间,右边的存储空间叫HASH,也就是说HASH是数据类型,他不是具体的一个数据,而是存储空间上的一堆数据。它底层有ziplist、hashtable两种数据编码。


ziplist 表,又称为压缩列表,是一种特殊编码的双链表,用于存储字符串或整数,从而提高内存使用效率,这也是HASH数据类型默认使用的编码格式。但内存使用率高了,那么它的查询操作速度相对降低,因为多了编码解码的操作。ziplist 是典型时间换空间的设计(一般索引是用空间换时间)。


hashtable 表,又称为哈希表,是HASH数据类型中,当数据过多或多长时由 ziplist 优化而来,底层数据结构与ziplist不同,且数据结构不可逆。具体使用哪种编码格式,Redis 会根据情况自己选择更合适的编码格式,这对于用户完全透明。


八、总结

通过上述五种数据存储结构的介绍,我们可以整理出以下表格:

图片.png

五种数据存储结构的介绍

数据库是用于存储数据的,为了不丢失数据每次写需要做持久化,也就是数据每次写都要存储在磁盘上。磁盘相对CPU、内存、缓存等设备,它的IO处理速度慢了几个数量级,即使是SSD,磁盘IO也是远低于内存的读写速率。所以数据库为了提高性能,就需要在磁盘IO上做出最佳选择。这些不同的数据存储结构,就是面对不同的数据以及业务场景,来提高数据库性能。当然现代数据库还要对数据进行压缩、解压、分布等等运算操作,则需要使用CPU等资源,这些不再本文论述范围内。


本文介绍了五种常见数据存储结构,另外还有图、表格、链式、R-TREE等数据结构并未涉及,当然本文也只是对数据库存储结构的知识抛砖引玉,有兴趣的同学可以对每一种数据存储结构做更详细和深入的学习。


最后

司马辽太杰是 NineData 工程师。NineData 向企业和个人提供高效、安全的数据库SQL开发、数据库备份、数据复制/迁移/集成、数据对比等功能,是一个SaaS服务开箱即用,可以快速提升企业SQL开发效率,保障企业数据安全。NineData 官网地址:https://ninedata.cloud

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
8月前
|
SQL 缓存 分布式数据库
【赵渝强老师】达梦数据库的线程结构
达梦数据库采用单进程、多线程结构,利用对称服务器架构实现高效资源利用与可扩展性。其核心线程类型包括监听线程(管理客户端连接)、I/O线程(处理数据页读写)、工作线程(执行数据操作)、调度线程(定时任务管理)和日志刷新线程(确保REDO日志刷盘)。通过合理分工与同步机制,达梦数据库实现了高性能与稳定性。视频讲解进一步详细介绍了各线程的功能与协作方式。
249 1
【赵渝强老师】达梦数据库的线程结构
|
8月前
|
存储 SQL NoSQL
【赵渝强老师】达梦数据库的逻辑存储结构
本文介绍了达梦数据库的存储结构,包括逻辑和物理存储两部分。逻辑存储结构由数据库(Database)、表空间(Tablespaces)、段(Segments)、簇(Cluster)和页(Page)组成。数据库是最大逻辑单元,包含所有表、索引等;表空间由数据文件组成,用于存储对象;段由簇构成,簇包含连续的数据页;页是最小存储单元。文中还提供了查询表空间、段和页大小的SQL语句,并附有视频讲解和示意图。
326 7
|
9月前
|
数据管理 关系型数据库 MySQL
数据管理服务DMS支持MySQL数据库的无锁结构变更
本文介绍了使用Sysbench准备2000万数据并进行全表字段更新的操作。通过DMS的无锁变更功能,可在不锁定表的情况下完成结构修改,避免了传统方法中可能产生的锁等待问题。具体步骤包括:准备数据、提交审批、执行变更及检查表结构,确保变更过程高效且不影响业务运行。
529 2
|
8月前
|
SQL 存储 缓存
【赵渝强老师】达梦数据库的内存结构
本文介绍了达梦数据库管理系统的内存结构,包括内存池、缓冲区、排序区和哈希区。内存池分为共享内存池和运行时内存池,能够提高内存申请与释放效率,并便于监控内存使用情况。缓冲区涵盖数据缓冲区、日志缓冲区、字典缓冲区和SQL缓冲区,用于优化数据读写和查询性能。排序区和哈希区分别提供排序和哈希连接所需的内存空间,通过合理配置参数可提升系统效率。文内附有具体配置示例及视频讲解,帮助用户深入理解达梦数据库的内存管理机制。
256 0
|
8月前
|
存储 SQL 安全
【赵渝强老师】达梦数据库的物理存储结构
本文介绍了达梦数据库的存储结构及各类物理文件的作用。达梦数据库通过逻辑和物理存储结构管理数据,包含配置文件(如dm.ini、sqllog.ini)、控制文件(dm.ctl)、数据文件(*.dbf)、重做日志文件(*.log)、归档日志文件、备份文件(*.bak)等。配置文件用于功能设置,控制文件记录数据库初始信息,数据文件存储实际数据,重做日志用于故障恢复,归档日志增强数据安全性,备份文件保障数据完整性,跟踪与事件日志辅助问题分析。这些文件共同确保数据库高效、稳定运行。
409 0
|
11月前
|
存储 数据采集 数据挖掘
CSV vs 数据库:数据存储的最佳选择是什么
本文介绍了爬虫数据存储中CSV和数据库的优缺点,分析了两者在不同场景下的适用性。CSV简单易用、资源消耗低,适合小量数据;数据库则在处理大量数据和复杂查询时表现出色,支持并发操作。通过Python代码示例,展示了如何使用多线程和爬虫代理IP技术将百度搜索数据存储到MySQL数据库中,适用于大型项目和复杂数据分析需求。
711 2
|
存储 移动开发 数据库
HTML5 Web IndexedDB 数据库常用数据存储类型
IndexedDB 支持多种数据存储类型,满足复杂数据结构的存储需求。它包括基本数据类型(如 Number、String、Boolean、Date)、对象(简单和嵌套对象)、数组、Blob(用于二进制数据如图像和视频)、ArrayBuffer 和 Typed Arrays(处理二进制数据)、结构化克隆(支持 Map 和 Set 等复杂对象),以及 JSON 数据。尽管不直接支持非序列化数据(如函数和 DOM 节点),但可以通过转换实现存储。开发者应根据具体需求选择合适的数据类型,以优化性能和使用体验。
|
存储 关系型数据库 分布式数据库
揭秘PolarDB:中国云原生数据库的超级英雄,如何颠覆传统数据存储?
在数字化时代,数据成为企业的核心资产,而云原生数据库则是推动企业转型的关键。PolarDB凭借其先进的存储计算分离架构,在性能、可靠性和易用性方面脱颖而出,成为国内领先的选择。它支持多种数据库引擎,提供多副本存储机制,并采用按量付费模式,有效降低管理和成本压力,助力企业实现高效、可靠的数字化转型。
243 1
|
存储 关系型数据库 分布式数据库
揭秘PolarDB:中国云原生数据库的超级英雄,如何颠覆传统数据存储?
【8月更文挑战第8天】在数字化时代,数据成为企业的核心资产。随着云技术的发展,企业纷纷向云端迁移,选择合适的云原生数据库至关重要。PolarDB凭借卓越性能、高可靠性和易用性在中国市场领先。它采用存储计算分离架构,支持独立扩展,提高处理大规模数据的效率和灵活性。多副本机制确保数据高可用性和持久性,优于单副本存储方案。兼容多种数据库引擎,提供丰富管理工具,降低迁移和维护成本。按量付费模式帮助企业有效控制成本。因此,PolarDB为企业数字化转型提供了强有力的支持。
293 1
|
Oracle 关系型数据库 数据库连接

热门文章

最新文章

下一篇
oss云网关配置