我创建了一个数据库,其中总共包含3个表以用于特定目的。所有表的总大小约为850 MB-非常精简...其中一个表包含约800 MB(包括索引)的数据和500万条记录(每天增加约6000条记录)。
该系统是PG-Windows,带有8 GB RAM Windows 7笔记本电脑,带有SSD。
我将2048MB分配为shared_buffers,将256MB分配为temp_buffers,将128MB分配为work_mem。
我对单个表多次执行单个查询-希望该表保留在RAM中(因此具有上述参数)。
但是,尽管我在执行过程中看到内存使用量激增(大约200 MB),但我看不到内存消耗至少保持500 MB(以便数据保留在内存中)。运行的所有postgres exe在任务管理器中显示2-6 MB的大小。因此,我怀疑LRU不会将数据保留在内存中。
平均查询执行时间约为2秒(非常简单的单表查询)...但是我需要将其降低到大约10-20毫秒,或者如果可能的话甚至更短,这纯粹是因为次数太多了,这是一样的只能通过将内容保留在内存中来执行。
有什么建议吗?
问候,
卡皮尔
最佳答案
即使整个数据库都缓存在RAM中,您也不应该期望postgres
进程会占用大量内存。
那是因为PostgreSQL依赖于操作系统缓冲区高速缓存中的缓冲读取。简而言之,当PostgreSQL执行read()
时,操作系统将查看是否将请求的块缓存在用于磁盘缓存的“空闲” RAM中。如果该块在高速缓存中,则操作系统几乎立即将其返回。如果该块不在缓存中,则OS将从磁盘读取该块,然后将其添加到磁盘缓存中,然后返回该块。后续读取将从高速缓存中获取它,除非其他块将其从高速缓存中移出。
这意味着,如果您有足够的可用内存来将整个数据库容纳在“可用”操作系统内存中,那么您就不会倾向于在磁盘上进行读取。
根据操作系统的不同,磁盘写入的行为可能会有所不同。 Linux将回写缓存“脏”缓冲区,并且即使已将它们写入缓存,仍会从缓存中返回块。除非Pg在fsync()
时使用COMMIT
强制将它们立即写入磁盘,否则它们会延迟将它们写回到磁盘。这样做时,它会将缓存的块标记为干净,但不会刷新它们。我不知道Windows在这里的行为。
关键是,即使没有PostgreSQL进程似乎使用大量RAM,PostgreSQL仍可以完全用1GB数据库运行RAM。 shared_buffers
太高只会导致双重缓存,并会减少操作系统可用于缓存块的RAM数量。
确切地知道RAM中缓存了什么并不容易,因为Pg依赖于操作系统缓存。这就是为什么我提到您 pg_fincore
的原因。
如果您使用的是Windows,那么这将不起作用,您实际上只需要依靠观察磁盘 Activity 即可。性能监视器是否显示大量未缓存的磁盘读取?操作系统内存监视是否显示OS中用于磁盘缓存的大量内存?
确保effective_cache_size
正确反射(reflect)用于磁盘缓存的RAM。这将帮助PostgreSQL选择适当的查询计划。
您在没有明显证据的情况下做出的假设是,您遇到的查询性能是由磁盘读取延迟来解释的,并且可以通过内存中缓存来改善它。可能根本不是这种情况。您需要查看explain analyze
输出和系统性能指标,以了解发生了什么情况。