sanjihan Asked: 2019-08-06 01:44:03 +0800 CST2019-08-06 01:44:03 +0800 CST 2019-08-06 01:44:03 +0800 CST 数据库与内存的直接交互——它是如何工作的? 772 我正在阅读一本关于数据库的书,其中的一章讨论了缓冲区管理器及其替代策略。 我注意到 DBMS 直接与内存交互,而不是要求操作系统与虚拟内存交互。那是对的吗?这种直接的沟通究竟是如何发生的?DBMS 允许分配多少内存?我从来没有接触过如此低级的函数调用,我很想看到一些解释和例子。 如果您不知道要搜索的正确关键字,那么在 google 上查找此类信息有点麻烦。 mysql mariadb 1 个回答 Voted Best Answer Rick James 2019-08-06T10:48:55+08:002019-08-06T10:48:55+08:00 让我们只讨论 ENGINE=InnoDB 的 MySQL/MariaDB。(这实际上是当今唯一使用的引擎。) 所有 InnoDB 活动都发生在 buffer_pool 中。 所有数据和每个二级索引由 16KB 块组成。 这些块根据需要被带入 buffer_pool,并根据需要刷新。 它使用 LRU(最近最少使用)算法来控制要弹出的块。(LRU 有一些小的调整,所以它不完全是LRU。) 因此,给 InnoDB大部分RAM,然后让它做它的事情是非常重要的。一个简单的经验法则: innodb_buffer_pool_size应设置为大约 70% 的 RAM。对于大多数应用程序,这是最重要的设置,也是唯一需要更改默认设置的设置。 将 buffer_pool 设置得太大可能会导致交换。但是,由于 InnoDB 将其视为一个大数组,这可能会导致大量的交换,从而大大降低 MySQL/MariaDB 的速度。 InnoDB 具有用于读取写入块的线程。特别是,刷新到磁盘在某种程度上是“在后台”完成的。这使得 anINSERT看起来比实际更快。 我在这里进一步讨论内存分配 使用“虚拟内存”访问文件是一种懒惰的做事方式。它适用于简单的情况。但是,数据库引擎需要高效且快速。当代码知道访问模式时,最好使用为此调整的访问方法。 例如,如果您要按顺序读取文件,最好(用于内存管理)在两个“小”缓冲区之间进行 ping-ping;一个被读入,一个被解析。(单个“循环”缓冲区是一个不错的选择。) 这种直接的沟通究竟是如何发生的? 因为所有内容都在 16KB 块中,所以有一个数字可以唯一标识此类内容。它相当大(20?字节)。它至少包括“表空间”号,以及表空间内的块号。这是取模 buffer_pool_instances 的数量来决定查看哪个实例。 在一个块内,有表的行或二级索引的行,或它所代表的 B+Tree(参见 Wikipedia)中的节点的行。 如果块不在 buffer_pool 中,它必须在读取发生时等待。但是,在读取发生之前,可能需要写入以清除某些块。通常,后台线程会刷新“脏”块,以便在 buffer_pool 中始终存在一些空闲块。(“免费”或“容易移除”,因为它们不脏。)
让我们只讨论 ENGINE=InnoDB 的 MySQL/MariaDB。(这实际上是当今唯一使用的引擎。)
因此,给 InnoDB大部分RAM,然后让它做它的事情是非常重要的。一个简单的经验法则:
innodb_buffer_pool_size
应设置为大约 70% 的 RAM。对于大多数应用程序,这是最重要的设置,也是唯一需要更改默认设置的设置。将 buffer_pool 设置得太大可能会导致交换。但是,由于 InnoDB 将其视为一个大数组,这可能会导致大量的交换,从而大大降低 MySQL/MariaDB 的速度。
InnoDB 具有用于读取写入块的线程。特别是,刷新到磁盘在某种程度上是“在后台”完成的。这使得 an
INSERT
看起来比实际更快。我在这里进一步讨论内存分配
使用“虚拟内存”访问文件是一种懒惰的做事方式。它适用于简单的情况。但是,数据库引擎需要高效且快速。当代码知道访问模式时,最好使用为此调整的访问方法。
例如,如果您要按顺序读取文件,最好(用于内存管理)在两个“小”缓冲区之间进行 ping-ping;一个被读入,一个被解析。(单个“循环”缓冲区是一个不错的选择。)
因为所有内容都在 16KB 块中,所以有一个数字可以唯一标识此类内容。它相当大(20?字节)。它至少包括“表空间”号,以及表空间内的块号。这是取模 buffer_pool_instances 的数量来决定查看哪个实例。
在一个块内,有表的行或二级索引的行,或它所代表的 B+Tree(参见 Wikipedia)中的节点的行。
如果块不在 buffer_pool 中,它必须在读取发生时等待。但是,在读取发生之前,可能需要写入以清除某些块。通常,后台线程会刷新“脏”块,以便在 buffer_pool 中始终存在一些空闲块。(“免费”或“容易移除”,因为它们不脏。)