在PostgreSQL数据库中定期同步数据的最有效方法是什么?

5

我在我的PostgreSQL 9.0.x数据库中有一个名为cached_projects的表,我主要通过Rails应用程序访问它,其模式如下:

create_table "cached_projects", :force => true do |t|
  t.string   "name",                               :null => false
  t.datetime "created_at",                         :null => false
  t.datetime "updated_at",                         :null => false
  t.boolean  "localization",    :default => false, :null => false
  t.integer  "base_project_id"
end

表格由一个Rake任务填充,该任务每隔N分钟运行一次并执行以下操作:
  • 从SOAP Web服务查询所有项目记录(在这个上下文中,“项目”只是由名称(字符串)和几个布尔和整数字段组成)。
  • 将DB中的项目列表与SOAP结果同步,丢弃不再存在于SOAP结果中的任何记录,并添加发现的任何新记录。

做这个周期性同步的最有效方法是什么?重要的是,DB中的行与SOAP结果中给出的记录完全匹配,没有多余的内容。

我可以想到两种解决方案,但不确定哪种是最快的(由于有数万条记录,性能是一个问题,我希望尽可能频繁地进行同步):

  1. 在每次同步期间,删除cached_projects中的所有行,并为通过SOAP服务找到的每个项目插入一个新行。

    这将实现具有完全相同数据集的目标,但是每次在DB中删除约50000行对性能会产生多大影响,假设其中绝大多数未更改?在DB中产生如此多的“变动”是否有缺点?

  2. 在每次同步期间,选择cached_projects中的所有行,并将它们存储在临时哈希变量中。循环处理SOAP记录,对于每个记录,检查它是否已经存在于DB中(使用临时哈希),保留我们发现的DB记录的ID列表,以便它们可以保留在DB中。在比较完所有内容之后,为任何新记录插入行,并删除不再应存在于表格中的记录。

    这是我的当前解决方案,虽然它也完全镜像数据,但在Rake任务中比较所有记录需要大量计算资源,每次同步需要花费约3-5分钟。(实际上,当DB表为空时,第一次同步会更快,但在随后的同步中,它必须与所有行进行比较,这更慢一些。)

我愿意接受其他建议或改进上述两个想法。到目前为止,我一直在寻找应用程序代码(基于Ruby的Rake任务)内的解决方案,但我也对将更多逻辑推入DB本身的想法感兴趣,因为我对那方面的事情了解得少。


我认为这个基本问题最好在 http://dba.stackexchange.com 上问。 - the Tin Man
我怀疑解决方案将在我的应用程序代码(使用Ruby)中实现,而不是在数据库或SQL中实现,因此我在这里发布了它,但也可以在DBA上查看,谢谢。 - Stuart M
2
你可以将XML转换为数据库中的临时表,然后使用一些SQL进行同步。或者也许更容易/更快的方法是整个替换表,甚至将XML转储到新表中并执行删除/重命名以替换旧表。 - mu is too short
1
理想情况下,SOAP服务应该具有可以连接的推送通知。这对每个人来说都更好。服务负载要少得多。我只是说一下。 :) - Jared Beck
@JaredBeck 同意。最终我们可能能够实现这一点(希望甚至可以修改它,不再使用SOAP),但今天我必须使用它来工作。 - Stuart M
显示剩余6条评论
1个回答

1
如果第一次同步比后续同步更快,这意味着将所有数据插入数据库比比较每个数据并修改现有表格要快。
我建议您使用TRUNCATE来删除表中的所有记录而不是删除,然后将所有记录插入表中。

http://en.wikipedia.org/wiki/Truncate_(SQL)


谢谢,这比删除整个表要好得多。我相信我最终会只截断整个表并每次重新插入行,因为这样做非常快速。 - Stuart M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接