2012-02-15 105 views
4

我一直在注意Postgres(8.3)中簡單聚合性能的一些問題。問題是,如果我有一個由(customer_id,order_id)唯一的表(比如200M行),那麼查詢select customer_id,max(order_id) from larger_table group by customer_id比執行以下操作的簡單Java/JDBC程序慢一個數量級以上:postgres綜合性能

1)初始化一個空的HashMap的customerMap(這將映射id - > max order size) 2)執行「select customer_id,order_id from larger_table」,並獲得一個流結果集3)迭代遍歷結果集排如下所示:

long id = resultSet.getLong("customer_id"); 
long order = resultSet.getLong("order_id"); 
if (!customerMap.containsKey(id)) 
    customerMap.put(id,order); 
else 
    customerMap.put(id,Math.max(order,customerMap.get(id))); 

預計這種性能差異?我不應該這樣想,因爲我認爲上述內容與內部發生的事情非常接近。它是否有證據表明db有錯誤/不正確的調整?

+3

請在您的聲明中包含「EXPLAIN ANALYZE」的輸出,以便我們看看您是否缺少索引。 – 2012-02-15 05:17:13

回答

6

這可能是您的work_mem設置太低。我會先檢查一下。最近我被這個問題困住了。第二個最可能的問題是您缺少外鍵索引。

展覽如下。

一般來說,有需要問每當數據庫性能看起來低於標準桿的幾個問題:

  1. 您是否使用了最新版本? 7.4和9.0之間的每個版本都會帶來顯着的性能提升 - 如果可以升級,建議使用。
  2. 您是否在真實數據上運行您的基準測試? PostgreSQL的查詢計劃程序將在同一張表上生成不同的計劃,其中包含不同的數據或不同數量的數據。確保你總是用真實的數據進行測試。
  3. 你的PostgreSQL配置是什麼樣的? work_mem設置開箱即用,我自己遇到涉及GROUP BY的情況,在這種情況下人爲地選擇了錯誤的計劃,因爲它根本不認爲它有足夠的工作內存來對結果進行排序。
  4. 是您的Java代碼與數據庫運行在同一臺機器上?如果沒有,你可能會看到計算機之間的差異,而不是方法之間的差異。
  5. 你錯過了什麼索引? PostgreSQL不會自動爲外鍵創建索引,只是主鍵。我也被這個咬了,但如果你谷歌周圍你可以找到一個腳本,將檢測並添加缺少的外鍵索引。

沒有檢查查詢計劃,再次猜測PostgreSQL爲給定查詢選擇了什麼實現策略並不是一個好主意。

+2

'work_mem'的補充:與JVM默認分配的內存相比,缺省設置是非常低的。如果Java可以將所有的'(customer,max_order_id)'元組保留在內存中,但是PostgreSQL不會......這將是一個不公平的遊戲。 ;-) – 2012-02-15 19:34:42

+2

工作內容竟然是罪魁禍首!謝謝 – ryan 2012-02-18 07:37:12