Mat*_*isz 28 mysql postgresql sql-server db2 size
在 PostgreSQL 和 SQL Server 中,默认页面大小为 8 KB,在 MySQL 中为 16 KB,在 IBM DB2 和 Oracle 中仅为 4 KB。
为什么这些页面尺寸如此之小?
是否有历史或内存使用原因?
Vér*_*ace 36
我正在运行 Linux(Fedora 34,64 位,两个内核,四个 CPU,32 GB RAM - PostgreSQL 13.3)。
如果我运行stat -f some_random_file如下:
[pol@fedora inst]$ stat -f blah.txt
File: "blah.txt"
ID: f1b798b1610e7067 Namelen: 255 Type: ext2/ext3
Block size: 4096 Fundamental block size: 4096
Blocks: Total: 322411548 Free: 316122834 Available: 299727775
Inodes: Total: 81960960 Free: 81739842
[pol@fedora inst]$
Run Code Online (Sandbox Code Playgroud)
注意:Block size: 4096= 4096 字节 = 32768 位。
现在,即使您有一个两字节长的文件 ( "Hi") - 它仍然会在磁盘上占用 4096 字节 - 它基本上是操作系统可以执行的最小 I/O。操作系统以 4K“块”的形式从磁盘中取出东西,然后以 4K 块的形式将它们吐回 - 请参阅此处以获取快速概述。您可能想在自己的系统上进行测试。
磁盘本身有自己的“原子”单位。对于 HDD,这通常是 512 字节,但请参阅上面的链接 - “在硬件级别,旧驱动器使用 512B 扇区,而新设备通常以更大的块(通常为 4kB 甚至 8kB)写入数据”。请参阅此处了解 HDD,了解此处了解 SSD。(感谢@RonJohn 的评论)。
同样,数据库将在块中读入和读出数据(也称为页面 - 该术语可能会令人困惑) - 如果您更改记录中的一个单独位,数据库仍然必须读取记录所在的整个页面并写入修改完成后将整个页面返回到磁盘。
在 PostgreSQL 上,默认块大小为 8K。
test_1=# SELECT name, setting, short_desc, extra_desc FROM pg_settings WHERE name like '%block%' or short_desc LIKE '%block%';
name | setting | short_desc | extra_desc
----------------+---------+----------------------------------------------+------------
block_size | 8192 | Shows the size of a disk block. |
wal_block_size | 8192 | Shows the block size in the write ahead log. |
(2 rows)
test_1=#
Run Code Online (Sandbox Code Playgroud)
重要的是,硬盘、操作系统和 RDBMS“原子单元”大小之间的差距不要太大 - 否则,您将面临页面撕裂的风险- 来自以下链接:
避免撕裂的页面
对于 Postgres 文件布局,Postgres 一次将数据读写到磁盘 8kb。大多数操作系统使用较小的页面大小,例如 4kb。如果 Postgres 运行在这些操作系统之一上,就会出现一个有趣的边缘情况。由于 Postgres 以 8kb 为单位写入磁盘,而操作系统以 4kb 为单位写入磁盘,如果在正确的时间断电,则 Postgres 正在执行的 8kb 写入可能只有 4kb 写入磁盘。这种边缘情况有时被称为“撕裂的页面”。Postgres 确实有一种解决页面撕裂的方法,但它确实增加了 Postgres 需要执行的 I/O 数量。
另外,请参见此处:
部分写入/撕裂的页面
那么什么是整页文章呢?正如 postgresql.conf 中的评论所说,这是一种从部分页面写入中恢复的方法——PostgreSQL 使用 8kB 页面(默认情况下),但堆栈的其他部分使用不同的块大小。Linux 文件系统通常使用 4kB 页面(可以使用较小的页面,但 4kB 是 x86 上的最大值),在硬件级别,旧驱动器使用 512B 扇区,而新设备通常以更大的块写入数据(通常为 4kB 甚至 8kB) .
因此,当 PostgreSQL 写入 8kB 页面时,存储堆栈的其他层可能会将其分解为更小的块,单独管理。这提出了关于写入原子性的问题。8kB 的 PostgreSQL 页面可能会被分成两个 4kB 的文件系统页面,然后分成 512B 的扇区。现在,如果服务器崩溃(电源故障、内核错误……)怎么办?
与与计算机科学相关的很多事情一样,这是一个权衡和妥协的问题——这是一个针对同一系统运行的 PostgreSQL基准测试,只是改变了块大小——来自帖子:
Samsung SSD 840, 500 GB TPS (txns/second)
blocksize=2k 147.9
blocksize=4k 141.7
blocksize=8k 133.9
blocksize=16k 127.2
blocksize=1MB 42.5
Run Code Online (Sandbox Code Playgroud)
因此,您可以看到幼稚的“使 db 块大小尽可能大”的方法效果不佳。所有我会说这是数据库基准测试是一个总的泥潭......对于某些应用1 MB可能不失为合适的-虽然偏离超过16 KB将需要相当大的理由。系统的默认参数就是——默认值——在最广泛的情况下选择得相当好......
关于。问题的历史部分 - 是的,其中很多都与磁盘进入 512 字节扇区时的历史有关...... HDD 尽管速度有所提高,并且锈蚀成分不断改进,但自第一个 HDD 以来基本上没有变化 - HDD 性能已经远远落后于 CPU 和 RAM ......容量增加了,速度没有那么多(见这里)——因此“NoSQL”潮流运动的诞生(但那是另一天的工作:-))!
这几天这个地区发生了很多事情......
如果你有兴趣-并有足够的时间-我已经仔细阅读它几次,但它是我上面的薪酬等级有点...有一篇文章在这里在Linux上的I / O以及它是如何被io_uring彻底改变了(见维基- 以及其中的链接)。
英特尔还提供了一个开源工具包,SPDK(存储性能开发工具包),它似乎(至少在我未经训练的眼睛看来)是某种允许用户空间进程直接访问硬件而无需通过内核的方式。 .这是一个关于如何将其应用于数据库的有趣观点。
而且,同样出现的是 (8) 字节可寻址存储......出于硬件设计人员最了解的原因,SSD(至少其中一些)也有块和页面......它们不是万能药(检查TLC SSD 和普通 HDD 写入速度 - 仅提高 30%)。
然而,在(远?)地平线上,有持久内存- 来自帖子:
8 字节原子性
持久性内存(例如英特尔傲腾 DC 持久性内存)本机逐字节运行,而不是像传统存储那样在数据块中运行。数据以最多 8 字节的块保存在持久内存中(同样,使用默认行为)。对于基于 BLOCK 构造的应用程序(如数据库),持久内存的 8 字节原子性可能是一个问题。写入 8,192 字节的数据(一个 8K 块)将保存在 1,024 个 8 字节的块中。电源故障或其他异常情况可能使数据块“破裂”或“撕裂”成碎片,块的一部分包含旧数据,而其他部分包含新数据。需要更改应用程序(例如数据库)以容忍这种类型的块破裂或撕裂。否则,这些实际上是损坏的数据块。
因此,我们可以看到这些系统仍然会出现诸如页面撕裂之类的问题——但它们确实提供了一种可能性——当数据库程序员赶上时——块大小 = 8 字节(不是8 KB)——你想改变一个BIGINT 的值,你所要做的就是读取 8 个字节并写入 8 个字节......
也许如果我们下降到这个级别,或者甚至是单个字节的特殊性,页面的整个概念将消失在磁盘、操作系统和 RDBMS 的窗口之外?我确信仍然会有文件系统——只是不确定它们将如何工作。
这是一个引人入胜的领域(问题+1!),尤其是对于数据库极客。
我将根据我对 SQL Server 的经验来回答,尽管我相信您提到的其他 RDBMS 的原因可能相同。
如果您查看Pages and Extents Architecture Guide文档,您会发现:
磁盘 I/O 操作在页级别执行。也就是说,SQL Server 读取或写入整个数据页。
这意味着当您请求数据时,它将按页而不是按行加载到内存中。考虑到这一点,请考虑以下图像作为页面的表示:
一个页面可以包含空白空间,如果默认大小是 1Gb 以每页保存更多数据,则新页面将有近 1Gb 的空白空间,并且只需要一些空间来快速分配服务器内存空间。
与内存相关的另一点是,只要您可以在内存中保留一个页面(SQL Server 中的页面预期寿命 (PLE)),您就不必在每次请求数据时花时间将其从磁盘读取到内存中。如果服务器内存消耗很快,页面很少,每个页面将更频繁地从内存中清除以分配新请求的页面,以便 SQL Server 可以使用它们。
Microsoft SQL Server 查询数据的基本原理是将所需的数据页从磁盘加载到缓冲池中并返回给客户端。如果缓冲区没有足够的空间来处理它,那么最旧的数据页面将被删除,以便为新页面腾出一些空间。
这些是您所说的页面很小的基本原因。
在这种情况下,小是一个主观术语。数据库中的Page Size设置越大,将存储到Page 的数据就越多,因此在需要从磁盘加载给定 Page 的任何时候都需要加载更多数据。你可以把网页作为计量单位的用于数据是如何物理存储在磁盘和磁盘是通常的最慢的硬件组件的服务器。
例如,如果您运行的查询只需要返回 4 KB 的数据,但您的页面大小设置为 1 GB,这意味着您需要等待从磁盘加载整个 1 GB 的数据才能提供服务4 KB 数据。很可能,这在性能方面不会很好。
此外,这只是假设您的 4 KB 数据连续存储在同一页面上,这将取决于您的数据和查询的谓词。例如,如果您的数据分布在 4 个页面上,那么现在需要从磁盘加载 4 GB 的数据才能仅提供 4 KB 的数据。
作为参考,对于单个整数或日期时间列,4 KB 的数据大约有 1,000 行。因此,即使我们讨论的是 10 列宽且平均数据大小为整数数据类型的数据集,4 KB 仍然可以容纳 100 行数据。
所以页面大小选择得不要太大,这样浪费的 I/O 会花在从磁盘加载比服务查询所需的更多的数据上,但相反也不能太小,否则你可能会因为增加而遇到性能瓶颈为少量数据加载多个页面所需的操作数。4 KB 到 16 KB 在数据库中已经在合理范围内,这也是默认设置的原因。如果您发现您的数据库工作负载和用例支持更改它,您可以随时调整它,但通常没有必要更改。