数据库存储在物理上是否连续,如果不连续那么如何保证读取速度?

2021-04-19 04:17:14 +08:00
 LeeReamond
如题。最近看 b+树莫名联想到数据库搜索的问题。b+树当然是很聪明的算法,不过从算法到落地中间还有一些过程,比如,

1 、关系型数据库比如 mysql 或者 oracle,其持久化时在物理上的地址是由系统管理还是由自身开辟出一段预留空间来管理?

2 、无论由谁管理,应该都避免不了碎片化的问题,由系统管理的话似乎碎片间隔在物理上会更大一些?不过只要碎片化,比如我们现在在使用机械硬盘,是否意味着极端情况下,比如索引数据储存在 n 个完全不相干的物理扇区,我们以为很快的索引,实际也要经过几次机械硬盘转动才能获取到结果?那也太慢了

3 、这是否意味着使用固态硬盘持久化效率远比机械硬盘高?在存储数据这库点上
1906 次点击
所在节点    问与答
16 条回复
ryd994
2021-04-19 04:32:39 +08:00
1. 所以要控制索引大小,保证索引能在内存里。
2. 数据库性能确实要看硬盘 iops
LeeReamond
2021-04-19 05:57:37 +08:00
@ryd994 说是这么说,但是实际上索引大小都是跟业务相关的吧,能加的都加,要不然就变成 ALL 搜索了。。
Mithril
2021-04-19 07:41:18 +08:00
1. 持久化管理本身就是数据库管理系统的一大功能。
2. 如果纯粹是从硬盘读取的话是有可能的,一般数据库会为了避免这样预先分配好一定大小的空间,而且也允许用户自己控制。比如直接分配个几百 G,或者每次按照一定大小增长。这样的话在一个空的硬盘上空间都会是连续的。
3. 是的。
qaweqa
2021-04-19 08:08:17 +08:00
有些实现会尽可能让页都按顺序存储。(也就是数据库参与管理)
dingwen07
2021-04-19 09:11:08 +08:00
第一个问题看情况,Oracle 支持 RAW 的块设备,这个时候就由 Oracle 来管理了。

似乎固态硬盘全是由主控管理的?
shakoon
2021-04-19 09:49:55 +08:00
我觉得楼主这个问题涉及到了应用程序层面、操作系统层面、硬件设备固件层面。每一个层面都有自己的优化算法可以对读写方式进行专门指定,但是一般来说,应用程序和操作系统都是没有办法改变硬件固件已经设定好的读写方式,但是如果觉得操作系统对硬件的调度算法对该应用不够最优,应用程序也是有可能直接操作读写硬件的,也就是跳过大部分操作系统常规的硬件调用 api 。最常见的场景就是,各种数据恢复软件、分区软件。
如 5 楼所言,常见数据库 oracle 、db2 较早已经提供了以 raw 方式读写磁盘以提供更优化的 io 性能。但这种模式下,应用程序对磁盘是完全独占的,即该分区将完全有应用所调度,其他程序是不能进行任何访问和操作的。
3 楼说的预先分配表空间的方式,对数据仓库类大量 insert 和 select 的应用来说效率很高,但是一旦涉及 update 和 delete,数据依然会产生物理上的不连续,当然相比完全由 os 管理还是要好得多。
固态硬盘有不少不会有碎片,只是由于其读写速度远高于磁盘的机械运动,碎片带来的影响在和磁盘相比上已经是若干数量级的区别了,所以一般都给忽略掉了。较大型的数据中心现在已经普遍在应用 ssd 阵列的存储设备了,和传统存储相比确实快了几倍(但没有到几个数量级的差别)。但是考虑到综合成本的问题,长期存储的数据主要还是在磁盘存储上,重要应用和需要经常读写的数据才放 ssd 上,毕竟二者价钱差异还是很大的。
cpstar
2021-04-19 10:12:02 +08:00
LZ 没有实操过吧,使用文件形式 MyISAM 存储的 mysql,过一段时间时间,表就得 optimize 一下清理碎片,INODB 会好一些。
这个事情涉及到 DBMS 的设计规则,最上层的表征当然是一个 SELECT 的效率,但是其中涉及到数据模型(表)的存储设计,操作系统的文件机制(磁盘分区格式)以及操作系统层以下的磁盘阵列机制(再往下就是单盘内部的缓存和存储组织形式)。
诚如楼上两回复所示,操作系统文件管理机制在其中,并不是最关键的,普遍 DBMS 会向 OS 申请一个较大的空间,然后文件系统决定是连续存储还是分片存储,所以为了进一步压榨,干脆把整盘独占给 DBMS——这个整盘并不是物理上的整盘而是经过了软硬件机制整合过的整块存储区。那么透过其本质,实际上就是 DBMS 在做一个文件存储系统,再进一步说,如果这台服务器事实上只处理 DBMS,那么是不是可以把 DBMS 和 OS 合并在一起,所以 Oracle 有数据库一体机,OS 经过调教,虽然还是 unix-like,但已经无关紧要了。
ch2
2021-04-19 10:22:36 +08:00
SSD 并不一定比 HDD 快
wakzz
2021-04-19 13:11:16 +08:00
1. MySQL 的 innodb 是通过预先分配磁盘空间的形式来减少碎片化问题,默认是每次申请 1M 大小的连续磁盘;
2. 每 1M 的连续读操作才遇到一次物理不连续,导致的性能消耗影响相对较小,甚至可以忽略;
3. 事实上数据库都有一个缓存层来缓存物理文件数据,性能正常的 innodb 引擎的缓存命中率要不低于 99%,当发生大量缓存命中失败导致大量磁盘读取时,更应该考虑如何提高缓存命中率,而不是物理磁盘碎片的问题;
chihiro2014
2021-04-19 13:17:23 +08:00
系统本身会有一个 rowid 的隐藏字段,我记得
数据库会尽量保证将数据连续保存,因为是机械硬盘,所以数据库设计的时候需要考虑降低磁盘臂旋转的问题,让每次读取 /写入数据时,能处理更多数据。
SSD 确实就没这问题。但将数据尽量放一起,性能确实会提高。遇上碎片化问题,PostgreSQL 是有个 vaccum 功能,可以清理,重新整理数据。
LeeReamond
2021-04-19 13:28:18 +08:00
@shakoon 感谢回复,不过这种所谓的 raw 方式操作磁盘,在现代操作系统中直接操作硬件应该是被禁止的,那么他是怎么实现所谓独占的呢。

@cpstar 我司数据库管理不由开发人员负责,我也是确实第一次听说实际生产是需要显示调用优化他才会优化,据我所知我们是没做,那为了保证服务可用性感觉又是一个大坑。。

@wakzz 缓存命中率这个问题,感觉是同一个问题啊,缓存层的实现应该只能执行一些很简单的逻辑,毕竟还是依赖物理,所以物理如何存储的应该就会影响缓存命中率
XiaoxiaoPu
2021-04-19 13:35:11 +08:00
@LeeReamond 不挂载文件系统,直接读写块设备(例如 /dev/sda)就可以做到了。极端点,连内核驱动都可以绕过,比如 SPDK
dblpx
2021-04-19 13:42:46 +08:00
每次申请 1M 的连续空间吗,innodb 每一页是 16k,B+树每个节点也是 16k 、16k 从磁盘读,我还以为申请空间也是每次 16k😨
dblpx
2021-04-19 13:43:51 +08:00
@wakzz 每次申请 1M 的连续空间吗,innodb 每一页是 16k,B+树每个节点也是 16k 、16k 从磁盘读,我还以为申请空间也是每次 16k😨
wakzz
2021-04-19 13:44:00 +08:00
@LeeReamond mysql 的 innodb 的缓存层是直接缓存的磁盘文件,不是对 sql 结果的缓存,而是对物理文件分片(每个分片默认 16K)的缓存。
比如一个查询涉及到多条行记录,innodb 会先去索引树找到对应记录的具体物理文件分片位置,然后到缓存层尝试命中这几条记录所在的物理文件分片。缓存命中不到后再去物理磁盘上读取文件分片数据,然后再在内存中聚合查询处理操作。
wakzz
2021-04-19 13:45:21 +08:00
@dblpx 是的,innodb 默认 16K 一个数据页,然后默认每 64 个数据页构成一个组,组就是物理磁盘空间申请的最小单位。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/771530

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX