我正在解析扑克手牌历史,并将数据存储在postgres数据库中。这是一个快速的视图:
我的性能相对较差,解析文件需要几个小时。我可以看到数据库部分占用了总程序时间的97%。因此,只需进行一点优化就可以更快地实现这一目标。
我现在设置的方式如下:
由于我为每一个动作发送查询,对于每个动作序列,对于每个游戏,我显然做了太多查询。我应该如何捆绑它们以获得最佳性能?我不介意重写一些代码,所以不要退缩。 :)
提前致谢。
CX
答案 0 :(得分:1)
如果没有任何查询,架构或Pg版本,很难回答这个问题。
一般而言,这些问题的答案是将工作分批更大的批次,以避免重复大量工作,最重要的是,通过在一次交易中完成所有工作。
你还没有说过关于交易的任何内容,所以我想知道你是否在自动提交模式下做了这一切。糟糕的计划。尝试将整个过程包装在BEGIN
和COMMIT
中。如果这是一个严重长时间运行的过程COMMIT
每隔几分钟/几十场游戏/无论如何,写一个检查点文件或数据库条目,你的程序可以用来从那一点恢复导入,并打开一个新的交易来携带上。
使用多值插入将有助于在同一个表中插入多行。例如:
INSERT INTO some_table(col1, col2, col3) VALUES
('a','b','c'),
('1','2','3'),
('bork','spam','eggs');
您可以使用synchronous_commit=off
和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
offers access to the COPY
api for bulk-loading,因此您的应用无需呼叫psql
即可在生成后加载CSV数据。