簡體   English   中英

數據幀寫入 Postgresql 性能不佳

[英]Dataframe writing to Postgresql poor performance

在 postgresql 中工作我有一個笛卡爾連接,產生了大約 400 萬行。 加入大約需要 5 秒,寫回數據庫需要大約 1 分 45 秒。

數據將需要在 python 中使用,特別是在 Pandas 數據幀中,所以我正在嘗試在 python 中復制相同的數據。 我應該在這里說,所有這些測試都在一台機器上運行,所以沒有任何東西通過網絡。

使用 psycopg2 和 pandas,讀入數據並執行連接以獲得 400 萬行(來自這里的答案: 熊貓中的笛卡爾積)持續不到 3 秒,令人印象深刻。

然而,將數據寫回數據庫中的表需要 8 分鍾(最佳方法)到 36 分鍾以上(加上我拒絕的一些方法,因為我不得不在 > 1 小時后停止它們)。

雖然我不希望重現“僅 sql”時間,但我希望能夠接近 8 分鍾(我認為 3-5 分鍾不會不合理)。

較慢的方法包括:

36 分鍾 - sqlalchemy 的 table.insert(來自此處的“test_sqlalchemy_core” https://docs.sqlalchemy.org/en/latest/faq/performance.html#im-inserting-400-000-rows-with-the-orm-而且它真的很慢

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 的工作。 有沒有辦法添加這些方法?

謝謝。 賈爾斯

我自己回答問題 1:似乎這個問題與 Postgresql(或者更確切地說是一般的數據庫)有關。 考慮到本文中的要點: https : //use-the-index-luke.com/sql/dml/insert我發現以下內容:

1) 從目標表中刪除所有索引導致查詢在 9 秒內運行。 重建索引(在 postgresql 中)又花了 12 秒,所以在其他時間下仍然很好。

2)只有一個主鍵,插入按主鍵列排序的行將花費的時間減少到大約三分之一。 這是有道理的,因為幾乎不需要或不需要對索引行進行改組。 我還驗證了這就是為什么我在 postgresql 中的笛卡爾連接首先更快的原因(即行按索引排序,純粹是偶然的),將相同的行放在臨時表中(無序)並從中插入實際上花了更長的時間。

3) 我在我們的 mysql 系統上嘗試了類似的實驗,發現刪除索引時插入速度也有同樣的提高。 然而,使用 mysql 似乎重建索引用盡了任何時間。

我希望這可以幫助任何在搜索中遇到這個問題的人。

我仍然想知道是否有可能刪除 python 中的 write to csv 步驟(上面的 Q2),因為我相信我可以在 python 中編寫一些比純 postgresql 更快的東西。

謝謝,吉爾斯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM