PostgreSQL:强制数据进入内存


Answers:


25

您可能对邮件列表主题之一有兴趣,Tom Lane(核心开发人员)回答了这个问题

[..]但是我的观点是,认为自己比LRU缓存算法更聪明的人通常会犯错误。如果该表被大量使用,它将留在内存中就好了。如果根据LRU算法,它没有足够多地用于保留在内存中,则可能确实应该将内存空间用于其他方面。[..]

您可能还会对一个SO问题感兴趣:https : //stackoverflow.com/questions/486154/postgresql-temporary-tables,也许更适合https://stackoverflow.com/questions/407006/need-to-load-the整个postgresql数据库到公羊


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

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

35

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将请求的块范围读入数据库缓冲区高速缓存。

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

请阅读手册以获取更多详细信息,引号位于此处。
Depesz也对此发表了博客


4

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

如果要在启动时准备数据库的页面缓存(例如,在重新启动或其他维护操作导致数据库忘记了缓存的所有内容之后),请编写执行以下操作的脚本:

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),然后可以有选择地扫描最常用的索引,而不是扫描将花费更长的时间的所有索引。


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

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

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

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

1

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

为了解决这个问题,确实编写了一个小的python脚本,该脚本在具有大索引的最重使用表上执行选择。运行仅需15分钟,并且没有性能延迟。


0

嗯,可能是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 *

您米格思还想读取索引和烤面包表,以相同的方式获取它们的oid。

顺便说一句,您为什么需要它?我相信postgresql和OS足够聪明,可以缓存最新数据并保持良好状态。缓存效率。


0

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

initdb -D e:\data

其中e:\是RamDisk的位置。


5
Windows上的PG对于生产站点是一个非常勇敢的选择,因为Windows上的PG比* nix(独立于RAM)慢。
DrColossos
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.