有没有一种系统的方法可以强迫PostgreSQL将特定的表加载到内存中,或者至少从磁盘中读取它以便系统将其缓存?

#1 楼

您可能对其中一个邮件列表主题感兴趣,汤姆·莱恩(Tom Lane)回答了该问题:


[..]但是我的看法是,
的人认为它们比通常误认为的LRU
缓存算法更聪明。如果该表已被大量使用,它将留在内存中就好了。如果根据LRU算法,它不足以充分使用它来保留在内存中,那么可能确实应该将内存空间用于其他方面。 [..]


您可能还会对一个SO问题感兴趣:https://stackoverflow.com/questions/486154/postgresql-temporary-tables,也许更适合https:// /stackoverflow.com/questions/407006/需要将整个Postgresql数据库加载到RAM中

评论


+1同样的想法也适用于其他RDBMS。

– gbn
2011年4月3日在16:45

是的,没有。我们将一些Oracle表锁定在内存中是因为我们知道它们可能不会被经常使用,但是在使用它们的情况下,延迟将成为杀手。一个数据库应该总是对数据库管理员有最终的决定权(另一个例子是提示查询优化器)。

– Gaius
2011年4月4日在9:17

#2 楼

Postgres 9.4最终添加了扩展,以将关系中的数据预加载到OS或数据库缓冲区高速缓存中(由您选择):

pg_prewarm


这可以实现完全操作性能更快。


在数据库中运行一次(详细说明在这里):

CREATE EXTENSION pg_prewarm;


那么预加载任何文件都非常简单给定的关系。基本示例:

SELECT pg_prewarm('my_tbl');


在搜索路径中找到名为my_tbl的第一个表,并将其加载到Postgres缓冲区缓存中。

或:<如果支持,则
SELECT pg_prewarm('my_schema.my_tbl', 'prefetch');
向运行中的系统发出异步预取请求,否则将引发错误。 prefetch
读取请求的块范围;与read不同,它是
同步的,并且在所有平台和内部版本上均受支持,但可能
较慢。 prefetch将请求的块范围读取到数据库中。


默认值为buffer,其影响最大(成本更高,效果最好)。

阅读手册以获取更多详细信息.Depesz也在博客上对此进行了介绍。

#3 楼

通常,如果您有足够的RAM,则通常可以信任数据库服务来很好地将您经常使用的内容保留在RAM中。某些系统允许您暗示该表应始终保存在RAM中(这对于不经常使用的小表很有用,但是当它们被使用时,尽快响应是很重要的),但是pgsql是否具有这样的表提示您在使用它们时需要非常小心,因为这会减少可用于缓存其他任何内容的内存量,因此可能会降低应用程序的整体速度。

如果您希望在其上预备数据库的页面缓存启动(例如,在重新引导或其他维护操作导致DB忘记了缓存的所有内容之后),然后编写执行以下操作的脚本:

SELECT * FROM <table>
SELECT <primary key fields> FROM <table> ORDER BY <primary key fields>
SELECT <indexed fields> FROM <table> ORDER BY <indexed fields>


(那为每个索引或过程重复最后一步,请注意以正确的顺序使ORDER BY子句中的字段正确运行。

运行上述操作后,应该已读取每个数据和索引页,依此类推将在RAM页面缓存中(至少暂时)。对于我们的应用程序数据库,我们有这样的脚本,它们在重新启动后运行,以便以后首次登录系统的用户不会感到响应速度变慢。您最好直接手写任何此类脚本,而不是扫描数据库定义表(例如MSSQL中的sys.objects / sys.indexes / sys.columns),然后可以有选择地扫描最常用的索引,而不是扫描所有需要花费更长时间的索引。

评论


这至少在PostgreSQL上不起作用。从共享缓冲区分配了一个较小的(256KB)环形缓冲区以进行顺序扫描,以防止使用整个缓冲区高速缓存。有关详细信息,请参见github.com/postgres/postgres/blob/master/src/backend/storage/…。您可以通过在大表中执行SELECT *,然后查看pg_buffercache表(来自pg_buffercache扩展)来验证这一点。

– hbn
2014年7月14日在11:09



@hbn大家好,但是这个保存线程中的这个家伙说它有效-dba.stackexchange.com/a/36165/55752

– cythargon
2015年3月9日,下午5:32

@scythargon可能会终止在OS缓存中,而不会在PostgreSQL缓冲区缓存中得到它。如果您不相信我,请尝试上面我建议的方法。

– hbn
15年4月15日在10:11

在Postgres 9.5中,我尝试了SELECT * FROM schema.table,并看到它将整个60GiB表加载到我的100GiB PostgreSQL缓冲区缓存中。

– sudo
17 Mar 7 '17 at 15:46

#4 楼

我遇到了类似的问题:
重新启动服务器服务后,所有已兑现的数据都掉了,许多查询在第一次调用时就真的很慢,这是因为查询的特定复杂性,直到所有必要的索引和数据都被兑现了。
这意味着,例如,用户必须在每个“项目”(执行时间1-3秒)和5000万行中的相关数据中击中一次,这样用户就不会再遇到任何不必要的延迟。用户需要花费前3个小时才能体验到令人讨厌的挂起,直到大多数使用的数据被兑现并且程序破坏了生产性能的一流水平,即使如此,结束时也只有2天,突然遇到了短暂的延迟,当您遇到较少的首次访问数据时...

为了解决这个问题,编写了一个小的python脚本,该脚本对具有大索引的最常用表进行选择。运行只花了15分钟,没有任何性能延迟。

#5 楼

嗯,可能是COPY命令会有所帮助。只需执行COPY到stdout并从中读取。可以使用pg_dump做到这一点:

pg_dump -U <user> -t <table> <database> > /dev/null


其他方法是找到所有表文件并运行cat <files> > /dev/null。这里是示例有关如何获取表文件名的信息:

# SELECT oid, datname FROM pg_database ;
  oid  |  datname  
-------+-----------                                                                                                                                          
<...>
 16384 | test
-- out of database is 16384
# SELECT oid, relname FROM pg_class WHERE relname like 'fn%';
  oid  | relname 
-------+---------
 24576 | fn
(1 row)
-- oid of our table is 24576


因此,表的文件为/ path / to / pgsql / data / base / 16384/24576 *

您同样想读取索引和Toast表,以相同的方式获取它们的oid。

BTW,为什么需要它?我相信postgresql和OS足够聪明,可以缓存最热的数据并保持良好状态。缓存效率。

#6 楼

我使用QSoft的RamDrive,该软件被基准为Windows最快的ramdisk。我只是用

initdb -D e:\data

其中e:\是RamDisk的位置。

评论


Windows上的PG对于生产站点是一个非常勇敢的选择,因为Windows上的PG比* nix(独立于RAM)慢得多。

– DrColossos
2011年4月11日在18:04