ArangoDB将所有数据存储在内存映射文件中。每个集合可以具有0到n个数据文件,默认文件大小为每个32 MB(请注意,此文件大小可以在全局或每个集合级别上进行调整)。从未有任何数据的空集合将不具有数据文件。对集合的第一次写入将创建数据文件,并且每当数据文件已满时,将自动创建新的数据文件。
默认情况下,集合以32 MB的块分配数据文件。如果您有许多但小型的集合,则可能会浪费一些内存。如果您拥有很少但大型集合,则潜在的浪费(数据文件末尾的空闲空间)可能并不重要。
每当ArangoDB操作从内存映射数据文件读取数据或向其写入数据时,操作系统都会首先将偏移量转换为页号。这是因为每个数据文件隐式地被分成特定大小的页面。页面的大小取决于平台,但假设页面大小为4 KB。因此,默认文件大小的数据文件将具有8192个页面。
操作系统将文件中的偏移量转换为页码后,会确保所请求的页的数据存在于物理内存中。如果该页尚未在物理内存中,则操作系统将发出页面错误以触发从磁盘或交换区加载所请求的页面。这最终会使完整的页面在RAM中可用,并且可以在此之后进行对页面数据的任何读取或写入。
所有这些都是由操作系统的虚拟内存管理器完成的。操作系统可以自由地将来自数据文件的许多页面映射到RAM中。例如,当顺序访问内存映射文件时,操作系统可能会聪明地预读许多页面,因此它们在实际访问时已经在物理内存中了。
操作系统还可以自由地交换数据文件的某些或全部页面。如果没有足够的物理内存可用于同时保留所有数据文件的所有页面,则可能会交换出页面。它还可以交换出一段时间内未使用的页面,以便为其他操作释放RAM。它可能会使用某些LRU算法来实现这一点。
操作系统的虚拟内存管理器的行为在不同的平台和实现中有很大差异。大多数系统也允许配置VM子系统。例如,下面是Linux VM子系统的一些参数。
因此,很难确定ArangoDB对于给定数量的集合及其数据文件实际上会使用多少物理内存。如果根本没有访问集合,则将数据文件映射到内存可能几乎不会使用任何RAM,因为操作系统可能已经完全或至少部分地将集合交换出去。如果集合被广泛使用,操作系统可能已将它们的数据文件完全映射到RAM中。但在两种情况下,内存都被视为内存映射。这意味着您可以拥有比物理RAM更高的虚拟内存使用量。
如前所述,当访问不在RAM中的页面时,操作系统需要进行大量工作,如果可能的话,应该尽量避免这种情况。如果您经常使用的集合的总大小超过物理RAM的大小,则当您访问这些集合时,操作系统别无选择,只能频繁地将页面交换出去并换入。使用SSD作为交换的介质可能比使用旋转HDD更好,但仍远远不及RAM访问速度快。简而言之:您活跃集合的数据(数据文件加索引)应尽可能适合物理RAM,否则您将看到大量磁盘活动。
除此之外,ArangoDB不仅为集合数据文件分配虚拟内存,还启动了一些V8线程(V8是ArangoDB中的JavaScript引擎),这些线程也使用虚拟内存。这个虚拟内存不是基于文件的。
在空的ArangoDB中,V8占用了大部分虚拟内存。例如,在我的64位计算机上,V8线程消耗约5 GB的虚拟内存(但ArangoDB总共只使用了140 MB RAM),而在我32位计算机上,V8线程使用约600-700 MB虚拟内存。在您的情况下,使用4.5 GB VM,我认为V8也是原因。
V8线程的虚拟内存使用量显然与启动的V8线程数相关。例如,增加启动参数--server.threads的值将启动更多的线程,并为V8使用更多的虚拟内存,降低该值将启动较少的线程并使用较少的虚拟内存。