1

我正在解析扑克手牌历史,并将数据存储在 postgres 数据库中。这是一个快速的视图: 在此处输入图像描述

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

我现在设置的方式如下:

  1. 将下一个文件读入字符串。
  2. 解析一个游戏并将其存储到对象 GameData 中。
  3. 对于每个玩家,检查我们是否在 std::map 中有他的名字。如果是这样; 将 playerids 存储在一个数组中,然后转到 5。
  4. 插入播放器,将其添加到 std::map,将 playerids 存储在数组中。
  5. 使用 playerids 数组,插入本轮投注的移动,将 moveids 存储在数组中。
  6. 使用 moveids 数组,插入一个movesequence,将movesequenceids 存储在一个数组中。
  7. 如果这不是最后一轮比赛,请转到 5。
  8. 使用 movesequenceids 数组插入游戏。
  9. 如果这不是最后一场比赛,请转到 2。
  10. 如果这不是最后一个文件,请转到 1。

因为我要为每一个动作、每一个动作序列、每场比赛发送查询,我显然做了太多的查询。我应该如何捆绑它们以获得最佳性能?我不介意重写一点代码,所以不要退缩。:)

提前致谢。

CX

4

1 回答 1

1

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

不过,总的来说,这些问题的答案是将工作分批成更大更粗的批次,以避免重复大量工作,最重要的是,通过在一个事务中完成所有工作。

您还没有说有关transactions的任何内容,所以我想知道您是否在自动提交模式下执行所有这些操作。糟糕的计划。尝试将整个过程包装在 aBEGINCOMMIT. COMMIT如果它是每隔几分钟/几十场比赛/任何时间运行的非常长时间的过程,请编写一个检查点文件或数据库条目,您的程序可以使用该文件从该点恢复导入,并打开一个新事务以继续。

在向同一个表中插入多行的情况下,使用多值插入会有所帮助。例如:

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

synchronous_commit=off您可以使用和 a提高提交率commit_delay,但如果您将工作批量处理成更大的事务,这不是很有用。

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

INSERT INTO the_table
SELECT * FROM the_table_import;

这样做时,CREATE TABLE ... LIKE很有用。

另一种选择 - 实际上是上述更极端的版本 - 是在您阅读并转换它们时将结果写入 CSV 平面文件COPY,然后将它们写入数据库。由于您使用 C++ 工作,我假设您正在使用libpq- 在这种情况下,您希望也使用libpqtypes. libpq提供对COPYapi 的访问以进行批量加载,因此您的应用在生成 CSV 数据后无需调用psql来加载它。

于 2012-08-25T02:23:44.417 回答