【问题标题】:Dataframe writing to Postgresql poor performance数据框写入 Postgresql 性能不佳
【发布时间】:2019-08-23 12:48:59
【问题描述】:

在 postgresql 中工作我有一个笛卡尔连接,产生了大约 400 万行。 连接需要约 5 秒,写回数据库需要约 1 分 45 秒。

这些数据需要在 python 中使用,特别是在 pandas 数据框中,所以我正在尝试在 python 中复制相同的数据。我应该在这里说所有这些测试都在一台机器上运行,所以没有任何东西通过网络。

使用 psycopg2 和 pandas,读入数据并执行连接以获得 400 万行(来自此处的答案:cartesian product in pandas)始终花费不到 3 秒,令人印象深刻。

然而,将数据写回数据库中的表需要 8 分钟(最佳方法)到 36 分钟以上(加上一些我拒绝的方法,因为我不得不在 >1 小时后停止它们)。

虽然我不希望重现“仅 sql”时间,但我希望能够接近 8 分钟(我认为 3-5 分钟不会不合理)。

较慢的方法包括:

36 分钟 - sqlalchemy 的 table.insert(来自此处的“test_sqlalchemy_core”https://docs.sqlalchemy.org/en/latest/faq/performance.html#i-m-inserting-400-000-rows-with-the-orm-and-it-s-really-slow

13 分钟 - psycopg2.extras.execute_batch (https://stackoverflow.com/a/52124686/3979391)

13-15 分钟(取决于块大小)- pandas.dataframe.to_sql(再次使用 sqlalchemy)(https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html)

最好的方法(约 8 分钟)是使用 psycopg2 的 cursor.copy_from 方法(在这里找到:https://github.com/blaze/odo/issues/614#issuecomment-428332541)。 这涉及首先将数据转储到 csv(通过 io.StringIO 在内存中),仅此一项就需要 2 分钟。

所以,我的问题:

1) 任何人有任何可能更快的方法将数百万行从 pandas 数据帧写入 postgresql?

2) cursor.copy_from 方法 (http://initd.org/psycopg/docs/cursor.html) 的文档指出源对象需要支持 read() 和 readline() 方法(因此需要 io.StringIO)。据推测,如果数据帧支持这些方法,我们可以省去对 csv 的写入。有没有办法添加这些方法?

谢谢。 贾尔斯

【问题讨论】:

  • 这能回答你的问题吗? Write fast pandas dataframe to postgres
  • 我将此标记为重复,尽管您的问题有很多关于不同方法速度的有价值信息。如果可能,请将其添加到关于该问题的问答中!
  • 谢谢,看起来答案是使用我上面的“最佳方法”。我已通过此处的链接在已接受的答案中添加了评论,以防它对任何人有所帮助。
  • 另外,不相信这是重复的 - 另一个是“你能加快这段代码的速度吗”,而这是“什么是最快的方法”。

标签: python pandas postgresql dataframe sqlalchemy


【解决方案1】:

自己回答问题 1: 似乎这个问题更多地与 Postgresql(或者更确切地说是数据库)有关。考虑到本文中提出的观点:https://use-the-index-luke.com/sql/dml/insert 我发现以下内容:

1) 从目标表中删除所有索引导致查询在 9 秒内运行。重建索引(在 postgresql 中)又花费了 12 秒,所以仍然远低于其他时间。

2) 在只有一个主键的情况下,插入按主键列排序的行将花费的时间减少到大约三分之一。这是有道理的,因为应该很少或不需要对索引行进行改组。我还验证了这就是为什么我在 postgresql 中的笛卡尔连接首先更快的原因(即,行是按索引排序的,纯粹是偶然的),将相同的行放在临时表中(无序)并从中插入实际上花了更长的时间。

3) 我在我们的 mysql 系统上尝试了类似的实验,发现删除索引时插入速度同样提高。但是,使用 mysql 似乎可以随时重建已用完的索引。

我希望这对在搜索中遇到此问题的其他人有所帮助。

我仍然想知道是否可以在 python 中删除写入 csv 步骤(上面的第二季度),因为我相信我可以在 python 中编写比纯 postgresql 更快的东西。

谢谢,贾尔斯

【讨论】:

    猜你喜欢
    • 2022-11-02
    • 1970-01-01
    • 2013-09-22
    • 2012-03-14
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多