【问题标题】:is it safe to call setval of curval + 10 in postgresql?在 postgresql 中调用 curval + 10 的 setval 是否安全?
【发布时间】:2019-07-11 09:28:51
【问题描述】:

我使用 Postgres 作为我的 java spring hibernate 项目的数据库。

为了提高插入性能,我使用池化序列,它要求数据库序列的增量值等于池大小(比如说 10)。

这会导致多个问题。手动插入在工作时需要模拟池化算法,或者每次使用 nextval 作为 id 将每个插入增加 10。

配置也更复杂,因为每个序列都需要配置(例如,不能按原样使用串行)。 此外,所有插入表的服务器需要具有相同的池大小,这会强制所有配置与数据库同步。

是否有可能实现一个序列算法,使类似setval('seq', curval('seq') + poolsize) 的东西让服务器选择它想要的池大小,同时保持任何高于 curval 的数字都可以免费使用的隐式合约。我特别询问调用两个方法来执行原子操作(例如 AtomicInteger addAndGet)的任何并发问题。

这引出了我的第二个问题,是否有任何 Postgres 插件可以将此行为添加到序列中?因为我知道这种行为是可以实现的。

【问题讨论】:

  • 为什么不简单地用cache 大小定义序列?我怀疑这种“合并序列”是否会有所改善。
  • 缓存大小也已设置。如果没有池,Hibernate 将为每个要插入的实体生成 nextval 调用,即使插入是批处理的。无论 nextval 的成本多么小(有或没有缓存),它每次都需要在数据库和服务器之间进行往返。
  • @SteveMarion 只是在检查...即使您配置了hibernate.jdbc.batch_size,您确定每次插入都会进行往返吗?
  • batch size 将配置有多少插入将被批处理在一起,但无论如何都会调用 nextval 来设置 ID。我看到它使用 ttddyy/datasource-proxy

标签: postgresql sequence


【解决方案1】:

您提出的方法容易受到竞争条件的影响。

一些选项:

  • 您可以将您的方法打包到一个 PostgreSQL 函数中,并使用 advisory lock 保护它免受并发调用。当然,这只有在所有对序列的使用都通过函数时才有效。

    详情请见my blog

  • 您可以使用 10 的 CACHE 来定义您的序列。您不会获得可变大小的批次,但该序列仅每 10 次访问一次,并且值缓存在您的数据库会话中。

    这是满足您要求的最有效方式。

【讨论】:

  • 关于缓存,它不会改变服务器不知道这一点的事实,它仍然会为它需要的每个 id 调用 nextval,即使内部数据库正在使用缓存来获取它。函数解决方案很有趣,但是锁只会阻塞其他函数调用,而不是序列本身?我的目标是允许使用 default=nextval() 进行手动插入
  • 我不明白你对CACHE 的疑虑。您只需要 SQL 语句中的序列值,然后调用 nextval() 将非常便宜,而且不需要额外的客户端-服务器往返。您不会调用 SELECT nextval(...) 然后在客户端代码中处理该值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-01
  • 1970-01-01
  • 2012-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多