我正在分析扑克手的历史,并将数据存储在postgres数据库中。这是一个快速的 View :

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

我现在设置的方式如下:

  • 将下一个文件读入字符串。
  • 解析一个游戏并将其存储到对象GameData中。
  • 对于每个玩家,请检查std::map中是否有他的名字。如果是这样的话;将玩家ID存储在数组中,然后转到5。
  • 插入播放器,将其添加到std::map,将播放器ID存储在数组中。
  • 使用playerids数组,插入此下注回合的棋步,将moveids存储在数组中。
  • 使用moveids数组,插入一个moveequence,并将moveequenceids存储在数组中。
  • 如果这不是最后一场比赛,请转至5。
  • 使用moveequenceids数组插入一个游戏。
  • 如果这不是最终的游戏,请转到2。
  • 如果这不是最后一个文件,请转到1。

  • 由于我要为每个 Action ,每个 Action 序列,每个游戏发送查询,因此我显然进行了太多查询。我应该如何 bundle 它们以获得最佳性能?我不介意重写一些代码,所以不要退缩。 :)

    提前致谢。

    CX

    最佳答案

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

    但是,总的来说,解决这些问题的方法是将工作分成更大的更粗的批处理,以避免重复很多工作,最重要的是,一次完成所有工作。

    关于事务,您还没有说什么,所以我想知道您是否在自动提交模式下完成所有这些操作。不好的计划。尝试将整个过程包装在BEGINCOMMIT中。如果每隔几分钟/几十场游戏/等等,COMMIT是一个长时间运行的过程,则编写一个检查点文件或DB条目,程序可以使用该条目或DB条目从该位置恢复导入,然后打开一个新事务进行。

    在向同一表插入多行的地方,使用多值插入会有所帮助。例如:

    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表(所有版本,但在 session 断开连接时丢失),然后在过程结束时将所有新行复制到主表并使用以下命令删除导入表:
    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,因此您的应用在生成CSV数据后,无需调出psql即可加载CSV数据。

    关于c++ - 如何优化将此数据写入Postgres数据库,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12111327/

    10-10 00:44
    查看更多