簡體   English   中英

提高postgreSQL中簡單左連接的性能

[英]Improving performance for simple left join in postgreSQL

我試圖在postgreSQL數據庫中的兩個表之間進行左連接,並且發現它需要大約14分鍾才能運行。 從現有的SO帖子來看,似乎這種類型的連接應該在幾秒鍾的數量級,所以我想知道如何提高此連接的性能。 我使用pgAdmin III在帶有8 GB RAMWindows 8機器上運行64-bit postgreSQL version 9.4.4 表結構如下:

表A:“parcels_qtr”:

包裹(文字)| yr(int)| qtr(文本)| lpid(pk,text)|

有1550萬行,每列都被編入索引,“lpid”是主鍵。 我還通過標准真空過程運行此表。

表B:“postalvac_qtr”:

包裹(文字)| yr(int)| qtr(文本)| lpid(pk,text)| vacCountY(int)|

有618,000條記錄,除“vacCountY”之外的所有字段都被編入索引,“lpid”是主鍵。 這也經歷了標准的真空過程。

運行數據輸出時,大約需要14分鍾。 使用explain (analyze, buffers)時需要花一點多時間。 第一個問題 - 這種性能差異完全可歸因於打印數據還是其他相關問題?

第二個問題,我可以將運行時間縮短到幾秒鍾嗎?

這是我的SQL代碼:

EXPLAIN (ANALYZE, BUFFERS)
select a.parcel,
   a.lpid,
   a.yr,
   a.qtr,
   b."vacCountY"
from parcels_qtr as a
left join postalvac_qtr as b
on a.lpid = b.lpid;

以下是我的解釋聲明的結果: https//explain.depesz.com/s/uKkK

我對postgreSQL很新,所以耐心和解釋會非常感激!

你要求DB做很多工作。 只看一下解釋計划,它是:

  1. 讀入整個表格( postalvac_qtr
  2. 基於lpid構建哈希
  3. 讀入另一個更大的表( parcels_qtr
  4. 散列15MM lpid的每一個,並將它們與現有的散列表相匹配

這些表有多大? 您可以通過發出以下命令來檢查

SELECT pg_size_pretty(pg_relation_size('parcels_qtr'));

我幾乎可以肯定,這個散列連接會溢出到磁盤,以及它的結構方式(“給我這兩個表中的所有數據”),但它絕不可能。

指數沒有幫助,也沒有。 只要你要求整個表,使用索引只會使事情變慢 - 無論如何postgres必須遍歷整個表,所以它也可以發出順序掃描。

至於為什么查詢具有與explain analyze不同的性能,我懷疑你是正確的。 1-向您的客戶端發送15M行,以及2-嘗試顯示它們的組合將導致實際查詢之外的顯着減速。

所以你能對它做點啥?

首先,這個查詢試圖做什么? 您希望多久獲取這兩個表中的所有數據,完全未經過濾? 如果它很常見,您可能需要考慮回到需求階段並找出解決該需求的另一種方法(例如,獲取給定年份和季度的所有數據是否合理?)。 如果它不常見(例如,每日出口),則1-14分鍾可能沒問題。

其次,你應該確保你的表沒有膨脹。 如果您在表上遇到重大updatedelete流量,則會隨着時間的推移而增加。 autovacuum守護進程可以幫助解決這個問題,但偶爾發出一個vacuum full也會有所幫助。

第三,您可以嘗試調整數據庫配置。 postgresql.conf ,有一些參數可用於服務器可用於磁盤高速緩存的預期RAM量,以及服務器可用於排序或連接的RAM量(在它溢出到磁盤之前)。 通過修改這些參數,您可以提高速度。

第四,您可能想要重新訪問您的架構。 您是否希望將年份和季度作為兩個單獨的列,或者您是否會更好地使用date類型的單個列? 你想要一個text鍵,或者你是否會更好地使用bigint (串行或從text列派生),這可能會更快加入? 兩個表中實際上是否需要parcelyrqtr字段,還是它們在一個表中重復數據?

無論如何,我希望這會有所幫助。

暫無
暫無

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

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