以可能的数据丢失为代价提高PostgreSQL的写入速度?

Xeo*_*oss 30 database postgresql

我喜欢PostgreSQL防崩溃,因为我不想花时间修复数据库.但是,我确信必须有一些我可以禁用/修改的内容,这样即使在断电/崩溃之前丢失了几条记录,插入/更新也会更快.我并不担心几条记录 - 只是整个数据库.

我正在尝试优化PostgreSQL以进行大量写入.插入100万行目前需要22分钟,这看起来有点慢.

如何加速PostgreSQL写入?

我调查过的一些选项(比如full_page_writes),似乎也存在破坏数据的风险,这不是我想要的.我不介意丢失数据 - 我只是不想要腐败.

更新1

这是我正在使用的表 - 这是因为大多数表将包含整数和小字符串,这个"样本"表似乎是我应该期待的最好的例子.

CREATE TABLE "user"
(
  id serial NOT NULL,
  username character varying(40),
  email character varying(70),
  website character varying(100),
  created integer,
  CONSTRAINT user_pkey PRIMARY KEY (id)
)
WITH ( OIDS=FALSE );
CREATE INDEX id ON "user" USING btree (id);
Run Code Online (Sandbox Code Playgroud)

我有大约10个脚本,每个脚本使用预准备语句一次发出100,000个请求.这是为了模拟我的应用程序将为数据库提供的实际负载.在我的应用程序中,每页有1个以上的插入.

更新2

我已经使用异步提交,因为我有

synchronous_commit = off

在主配置文件中.

Gre*_*ith 58

在22分钟内插入的1M记录可达到758条记录/秒.这里的每个INSERT都是对磁盘的单独提交,最终具有预写日志和数据库组件.通常情况下,我希望即使是具有电池备份缓存的优质硬件,您也将幸运地达到3000次/秒.所以如果这是没有这种写入加速的常规硬件,那么你实际上并没有做得太糟糕.在这种情况下,正常限制在500到1000次提交/秒范围内,没有针对这种情况进行特殊调整.

至于那些看起来像什么,如果你不能让提交包括更多的记录,你加快这个的选择包括:

  • 关闭synchronous_commit(已完成)

  • 增加wal_writer_delay.当synchronous_commit关闭时,数据库假脱机将提交每200ms写入一次.如果您想通过向上调整此值,可以使用几秒钟,这只会增加崩溃后数据丢失的大小.

  • 将wal_buffers增加到16MB,只是为了使整个操作更有效.

  • 增加checkpoint_segments,以减少常规数据写入磁盘的频率.你可能想要至少64个.缺点是磁盘空间使用量增加,崩溃后恢复时间更长.

  • 增加shared_buffers.这里的默认值很小,通常为32MB.您必须增加系统必须分配的UNIX共享内存量.完成后,有用的值通常不超过总RAM的1/4,最高可达8GB.这里的增益率超过256MB,从默认值增加到那里可能真的有用.

这就是它.你触摸的任何其他可能有帮助的东西都可能导致崩溃中的数据损坏; 这些都是完全安全的.


Mar*_*rkR 5

22分钟1万行似乎并不认为慢,特别是如果你有很多指标。

你是怎么做插入的?我认为您使用的是批量插入,而不是每笔交易一行。

PG 是否支持某种批量加载,例如从文本文件中读取或向其提供 CSV 数据流?如果是这样,最好建议您使用它。

请发布您用来加载 1M 记录的代码,人们会提供建议。

请发帖:

  • 为您正在加载的表创建 TABLE 语句
  • 您用于加载的代码
  • 数据的小例子(如果可能)

编辑:似乎 OP 对批量插入不感兴趣,但正在对许多单行插入进行性能测试。我将假设每个插入都在它自己的事务中。

  • 考虑在客户端对每个节点的插入进行批处理,将它们写入临时文件(希望持久/健壮),并拥有一个守护进程或一些定期进程,以合理大小的批次异步执行未完成记录的批量插入。
  • 根据我的经验,这种针对每个设备的批处理机制确实在审计数据(如数据仓库应用程序)中提供了最佳性能,其中数据不需要刚刚进入数据库。它还为应用程序提供了针对数据库不可用的弹性。
  • 当然,您通常会有多个端点设备创建审计记录(例如,电话交换机、邮件中继、Web 应用程序服务器),每个设备都必须有自己的完全独立的这种机制的实例。
  • 这是一个非常“聪明”的优化,它在应用程序设计中引入了很多复杂性,并且有很多可能发生错误的地方。除非你真的确定你需要它,否则不要实施它。

  • @MarkR:您对索引的评论让我想起 Xeoncross 可以做的另一件事:在加载数据之前删除索引,然后在加载完所有内容后重新创建它们。是的 Postgres 支持使用 `COPY` 命令批量加载 CSV (2认同)