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

Stu*_*t M 5 ruby sql postgresql synchronization ruby-on-rails

我的 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
Run Code Online (Sandbox Code Playgroud)

该表由 Rake 任务填充,该任务每N分钟运行一次并执行以下操作:

  • 从 SOAP Web 服务查询所有项目记录(此上下文中的“项目”仅由名称(字符串)和几个布尔值和整数字段组成)。
  • 将数据库中的项目列表与 SOAP 结果同步,丢弃 SOAP 结果中不再存在的任何记录,并添加找到的任何新记录。

进行这种定期同步的最有效方法是什么?重要的是数据库中的行与 SOAP 结果中给出的记录完全匹配,没有任何额外内容。

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

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

    这将实现拥有完全相同的数据集的目标,但是假设数据库中的绝大多数行保持不变,每次删除数据库中约 50,000 行的成本会有多大?数据库中存在如此多的“流失”是否有负面影响?

  2. 在每次同步期间,选择 中的所有行cached_projects,将它们存储在临时哈希变量中。循环遍历 SOAP 记录,对于每一条记录,检查它是否已经在数据库中(使用临时哈希),保留我们找到的数据库记录的 ID 列表,以便它们可以保留在数据库中。比较所有内容后,插入任何新记录的行,删除不应再出现在表中的记录的行。

    这是我当前的解决方案,虽然它也准确地反映了数据,但比较 Rake 任务中的所有记录是相当计算密集型的,每次同步大约需要 3-5 分钟。(实际上,第一次同步,当数据库表为空时,它会更快,但在后续同步中,它必须与所有行进行比较,这会更慢。)

我愿意接受其他建议或对这些想法的改进。到目前为止,我一直在研究我的应用程序代码中的解决方案(基于 Ruby 的 rake 任务),但我也对将更多逻辑推入数据库本身的想法感兴趣,因为我对这方面不太熟悉东西的。

小智 1

如果您的第一次同步比后续同步更快,这意味着将所有数据插入数据库比比较每个数据并修改现有表更快。

我建议您使用TRUNCATE删除表中的所有记录而不是删除,然后将所有记录插入表中。

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