如何优化将此数据写入postgres数据库

时间:2012-08-24 14:27:14

标签: c++ sql database postgresql optimization

我正在解析扑克手牌历史,并将数据存储在postgres数据库中。这是一个快速的视图: enter image description here

我的性能相对较差,解析文件需要几个小时。我可以看到数据库部分占用了总程序时间的97%。因此,只需进行一点优化就可以更快地实现这一目标。

我现在设置的方式如下:

  1. 将下一个文件读入字符串。
  2. 解析一个游戏并将其存储到对象GameData中。
  3. 对于每个玩家,检查我们是否在std :: map中有他的名字。如果是这样;将playerids存储在一个数组中并转到5。
  4. 插入播放器,将其添加到std :: map,将播放器存储在一个数组中。
  5. 使用playerids数组,插入此轮次的移动,将移动数据存储在数组中。
  6. 使用moveids数组,插入movesequence,将movesequenceids存储在数组中。
  7. 如果这不是最后一轮比赛,请转到5.
  8. 使用movesequenceids数组,插入游戏。
  9. 如果这不是最后一场比赛,请转到2.
  10. 如果这不是最后一个文件,请转到1.
  11. 由于我为每一个动作发送查询,对于每个动作序列,对于每个游戏,我显然做了太多查询。我应该如何捆绑它们以获得最佳性能?我不介意重写一些代码,所以不要退缩。 :)

    提前致谢。

    CX

1 个答案:

答案 0 :(得分:1)

如果没有任何查询,架构或Pg版本,很难回答这个问题。

一般而言,这些问题的答案是将工作分批更大的批次,以避免重复大量工作,最重要的是,通过在一次交易中完成所有工作。

你还没有说过关于交易的任何内容,所以我想知道你是否在自动提交模式下做了这一切。糟糕的计划。尝试将整个过程包装在BEGINCOMMIT中。如果这是一个严重长时间运行的过程COMMIT每隔几分钟/几十场游戏/无论如何,写一个检查点文件或数据库条目,你的程序可以用来从那一点恢复导入,并打开一个新的交易来携带上。

使用多值插入将有助于在同一个表中插入多行。例如:

INSERT INTO some_table(col1, col2, col3) VALUES
('a','b','c'),
('1','2','3'),
('bork','spam','eggs');

您可以使用synchronous_commit=offcommit_delay来提高提交率,但如果您将工作分配到更大的事务中,则这不是很有用。

一个非常好的选择是将新数据插入 UNLOGGED(PostgreSQL 9.1或更新版)或TEMPORARY表(所有版本,但在会话断开时丢失) ),然后在进程结束时将所有新行复制到主表中,并使用以下命令删除导入表:

INSERT INTO the_table
SELECT * FROM the_table_import;

执行此操作时,CREATE TABLE ... LIKE非常有用。

另一种选择 - 实际上是上述的更极端版本 - 是在您阅读并转换它们时将结果写入CSV平面文件,然后 COPY 他们进入数据库。由于您使用的是C ++,我假设您正在使用libpq - 在这种情况下,您希望也使用libpqtypeslibpq offers access to the COPY api for bulk-loading,因此您的应用无需呼叫psql即可在生成后加载CSV数据。