簡體   English   中英

使用JDBC在PostgreSQL上緩慢插入

[英]Slow insert on PostgreSQL using JDBC

我在一個系統上工作,該系統將數據從雲系統下載到本地數據庫(PostgreSQL,MySQL,...)。 現在我遇到了PostgreSQL性能問題,因為插入數據需要花費大量時間。

許多列和數據的大小可能會有所不同。 在一個示例項目中,我有一張大約一張桌子。 170列。 有一個唯一索引 - 但即使在刪除索引后,插入的速度也沒有改變。

我正在使用JDBC驅動程序連接到數據庫,我正在以250行的批量插入數據(使用NamedParameterJdbcTemplate )。

我花了大概。 在Postgres上插入數據需要18秒 MySQL上的相同數據集只花了我一秒鍾 這是一個巨大的差異 - 它來自哪里? Postgres JDBC驅動程序是慢的嗎? 是否可以以某種方式配置以使其更快? 我錯過了別的什么嗎? Postgres和MySQL之間的區別是如此巨大。 任何其他想法如何讓它更快?

我做了一個示例項目,可以在Github上找到 - https://github.com/varad/postgresql-vs-mysql 一切都發生在LetsGo類的“run”方法中。

看來這是Spring“bug”和驅動程序“bug”的組合。

每次調用setValue()時,Spring都會嘗試確定列的數據類型。 它通過調用PreparedStatementMetaData.getParameterMetaData()做到這一點

這顯然會導致一個“准備”語句被發送到數據庫本身非常快(我的筆記本電腦上的時間不超過1毫秒)但是因為每個的每列調用它總共需要很多時間(這是調用每個非null值,導致大約23.000次調用)

在某種程度上,這更像是一個Spring bug然后是一個驅動程序錯誤,因為沒有緩存參數元數據並不真正有意義(至少在我看來)。 MySQL JDBC驅動程序不支持getParameterMetaData() ,Spring知道這一點,所以這個“bug”沒有出現在MySQL中,因為spring從不調用該方法。

我不確定Postgres的JDBC驅動程序行為是否可歸類為錯誤,但如果驅動程序在第一次調用后緩存該元數據,那肯定會很好。

Spring可以說服不通過屬性spring.jdbc.getParameterType.ignore獲取語​​句元數據

所以通過:

System.setProperty("spring.jdbc.getParameterType.ignore", "true");

在行之前

LetsGo letsGo = new LetsGo();

此行為已禁用。

必須 Spring初始化之前設置該屬性。

當我對您的示例項目執行此操作時,插入在我的筆記本電腦上運行500毫秒。


編輯

在看到有關使用Postgres-NG驅動程序的評論之后,我挖掘了“官方”驅動程序和NG驅動程序的來源,並且NG驅動程序在第一次調用后確實緩存了參數元數據,而官方驅動程序沒有解釋為什么使用NG驅動程序要快得多(不在Spring中禁用調用)

嘗試使用pgjdbc-ng驅動程序,然后比較您的結果。

它可以在這里找到: http//impossibl.github.io/pgjdbc-ng/

我希望你使用的是DB Connection Pool。 你可以試試C3P0。 Spring(JDBCTemplate)不提供連接池實現。

暫無
暫無

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

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