我的理解是,当DBMS想要读取块x时,它发出一个普通的读取指令。这与任何其他请求读取的应用程序没有区别。
我不是在寻找通用答案(我已经得到了它们并阅读了论文)。我正在寻找所描述问题的详细答案。 请参见Java应用程序从文件读取是否会调用系统调用?
根据您的另一个问题,以下是进一步了解:
当DBMS必须从磁盘读取页面时,它将涉及至少一个系统调用。此时,大多数DBMS将页面放入其自己的缓冲区中。(它们也会出现在操作系统的缓冲区中,但这不重要。)
因此,我们有一个系统调用。但是,我们可以避免任何进一步的系统调用。这是可能的,因为DBMS正在将页面缓存在其自己的内存空间中。当DBMS决定需要某个页面时,它将首先检查并查看它是否在其缓存中。如果是,它将从那里检索而不使用任何系统调用。
DBMS可自由以最有利于其IO需求的方式过期其缓存中的页面。由于操作系统还有其他事情要处理,因此操作系统的缓存以更一般的方式过期。例如,DBMS通常会使用大量内存来缓存页面,因为它知道磁盘IO是它可以执行的最昂贵的操作之一。操作系统不会这样做,因为它必须平衡磁盘IO的成本与为其他应用程序留出内存的成本。
这主要是性能问题。数据库管理系统具有高度特定和不寻常的I/O需求。
操作系统可能有许多进行I/O并填充其缓冲区以产生各种缓存数据的进程。
当然,还有一个问题是大小和何时缓存(与更通用的设备缓存相比,数据库管理系统可以更好地为其需要执行高效缓存)。
此外,一般“块”可能实际上会产生相当大的I/O负担,而数据库管理系统理想情况下不希望承担这种负担;它自己的缓存可以调整得更好,以使其与磁盘上数据的布局更好地配合,从而能够最小化I/O。
另一个问题是索引和类似手段加速查询的问题,如果缓存实际上“知道”这些意味着什么,这当然会更好。
真正的问题在于文件缓存不在DBMS使用的文件系统中;它在内核中并由系统中所有驻留的文件系统共享。从内核读取的任何内存都必须复制到用户空间:这就是你所读到的核心对核心移动。
除此之外,还有一些其他原因,你不能依赖系统缓冲池:
我知道这个问题很老,但它被列为未回答的问题。
基本上:
所以...要将数据从内核地址空间传输到DBMS的地址空间,无法避免进行系统调用或页面错误。
您正确地指出,访问操作系统缓冲池管理器中的数据不比普通的read()调用更昂贵。(实际上,它是通过普通的read调用完成的。)然而,Stonebraker并没有谈论那个。他特别讨论了DBMS的缓存需求,在数据从磁盘读取并存在RAM中之后。
实际上,他的意思是操作系统的缓冲池缓存对于数据库管理系统来说太慢了,因为它存储在不同的地址空间中。他建议在同一进程(因此在相同的地址空间)中使用本地缓存,这可以为像重度命中缓存的DBMS应用程序提供显着的加速,因为它将消除系统调用开销。顺便提一句,我相信Stonebraker于1981年发表的那篇论文实际上是在mmap之前。他将它提及为未来工作:“将文件系统作为共享虚拟内存的一部分(例如Pilot[16])提供的趋势可能会为这个问题提供一个解决方案。”