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=#
与内存相关的另一点是,只要您可以将页面保留在内存中(SQL Server 中的 Page Life Expectancy (PLE)),您就不必在每次请求数据时都花时间将其从磁盘读取到内存中。如果服务器内存被少量页面快速消耗,则将更频繁地从内存中清除每个页面以分配新请求的页面,以便 SQL Server 可以使用它们。
Microsoft SQL Server 查询数据的基本原理是将必要的数据页从磁盘加载到缓冲池中,然后返回给客户端。如果缓冲区没有足够的空间来处理它,那么最旧的数据页将被删除,以便为新页腾出一些空间。
我正在运行 Linux(Fedora 34、64 位、两个内核、四个 CPU、32 GB RAM - PostgreSQL 13.3)。
如果我运行
stat -f some_random_file
如下:注意:
Block size: 4096
= 4096 字节 = 32768 位。现在,即使您有一个长度为两个字节的文件
"Hi"
(操作系统将磁盘上的内容作为 4K“块”取出,然后以 4K 块的形式返回 - 请参阅此处以获取快速概览。您可能想在自己的系统上进行测试。磁盘本身有自己的“原子”单元。对于 HDD,这通常是 512 字节,但请参见上面的链接 - “在硬件级别,旧驱动器使用 512B 扇区,而新设备通常以更大的块(通常为 4kB 甚至 8kB)写入数据”。有关HDD,请参见此处,有关 SSD ,请参见此处。(感谢@RonJohn 的评论)。
同样,数据库将以块的形式读取和读取数据(也称为页面 - 术语可能会令人困惑) - 如果您更改记录中的一个单独的位,数据库仍然必须读取记录所在的整个页面并写入修改完成后将整个页面放回磁盘。
在 PostgreSQL 上,您有 8K 的默认块大小。
重要的是 HDD、操作系统和 RDBMS“原子单元”大小之间没有太大的差距 - 否则,你会冒着撕裂页面的风险- 从链接:
另外,请参见此处:
与许多与计算机科学相关的东西一样,这是一个权衡和妥协的问题——这里是 PostgreSQL 在相同系统上运行的基准,只是改变了块大小——来自帖子:
因此,您可以看到一个天真的“使 db 块大小尽可能大”的方法效果不佳。关于这一点我要说的是,数据库基准测试完全是一个泥潭……对于某些应用程序来说,1 MB可能很合适——尽管超出 16 KB 需要相当大的理由。系统的默认参数就是 -默认值- 在最广泛的情况下选择得相当好......
回覆。问题的历史部分 - 是的,很多都与磁盘进入 512 字节扇区时的历史有关...... HDD,尽管速度有所提高,锈蚀成分的逐步改进,但自第一个 HDD 以来基本上没有变化 - HDD 的性能已经远远落后于 CPU 和 RAM...容量增加了,但速度没有那么多(见这里)——因此“NoSQL”
潮流运动的诞生(但那是另一天的工作:-))!这几天,这个地区发生了很多事情......
如果你有兴趣 - 并且有时间 - 我已经仔细阅读了几次,但它比我的工资等级略高......这里有一篇关于Linux I/O 的文章以及它是如何被 io_uring 彻底改变的(参见wiki - 以及其中的链接)。
英特尔还提供了一个开源工具包,即SPDK(存储性能开发工具包),它似乎(至少在我未经训练的人看来)是某种允许用户空间进程直接访问硬件而无需通过内核的方式。 .这是关于如何将其应用于数据库的有趣观点。
而且,同样出现在现场的是(8)字节可寻址存储......由于硬件设计人员最熟悉的原因,SSD(至少其中一些)也有块和页面......它们不是灵丹妙药(检查出 TLC SSD 和普通 HDD 写入速度 - 只有 30% 的增益)。
然而,在(远?)地平线上,有持久记忆——来自帖子:
因此,我们可以看到这些系统仍然会出现诸如撕裂页面之类的问题- 但它们确实提供了可能性 - 当数据库程序员赶上时 - 块大小 = 8 字节(而不是8 KB) - 您想要更改BIGINT 的值,你所要做的就是读 8 个字节,写 8 个字节...
也许如果我们下降到这个级别,或者甚至是单个字节的特异性,那么对于磁盘、操作系统和 RDBMS,页面的整个概念就会消失?我确信仍然会有文件系统——只是不确定它们将如何工作。
这是一个引人入胜的领域(问题+1!),尤其是对于数据库极客。
我将根据我使用 SQL Server 的经验来回答,尽管我相信原因可能与您提到的其他 RDBMS 相同。
如果您查看Pages and Extents Architecture Guide文档,您会发现:
这意味着当您请求数据时,它将按页而不是按行加载到内存中。考虑到这一点,将以下图像视为页面的表示:
一个页面可以包含空白空间,如果默认大小是 1Gb 来容纳每页更多的数据,一个新页面将有近 1Gb 的空白空间,并且只需要一些空间来快速分配您的服务器内存空间。
与内存相关的另一点是,只要您可以将页面保留在内存中(SQL Server 中的 Page Life Expectancy (PLE)),您就不必在每次请求数据时都花时间将其从磁盘读取到内存中。如果服务器内存被少量页面快速消耗,则将更频繁地从内存中清除每个页面以分配新请求的页面,以便 SQL Server 可以使用它们。
这些是您所说的页面很小的基本原因。
在这种情况下,小是一个主观的术语。数据库中的Page Size设置越大,存储到Page的数据就越多,因此在需要从磁盘加载给定 Page 的任何时候都需要加载更多的数据。您可以将页面视为数据在磁盘上物理存储方式的度量单位,而磁盘通常是服务器最慢的硬件组件。
例如,如果您运行的查询只需要返回 4 KB 的数据,但您的 Page Size 设置为 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 在数据库中一直处于合理的范围内,这就是为什么它是默认的。如果您发现您的数据库工作负载和用例支持更改它,您可以随时调整它,但通常不需要更改。