[英]Improving performance for simple left join in postgreSQL
我試圖在postgreSQL數據庫中的兩個表之間進行左連接,並且發現它需要大約14分鍾才能運行。 從現有的SO帖子來看,似乎這種類型的連接應該在幾秒鍾的數量級,所以我想知道如何提高此連接的性能。 我使用pgAdmin III
在帶有8 GB RAM
的Windows 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做很多工作。 只看一下解釋計划,它是:
postalvac_qtr
) lpid
構建哈希 parcels_qtr
) lpid
的每一個,並將它們與現有的散列表相匹配 這些表有多大? 您可以通過發出以下命令來檢查
SELECT pg_size_pretty(pg_relation_size('parcels_qtr'));
我幾乎可以肯定,這個散列連接會溢出到磁盤,以及它的結構方式(“給我這兩個表中的所有數據”),但它絕不可能。
指數沒有幫助,也沒有。 只要你要求整個表,使用索引只會使事情變慢 - 無論如何postgres必須遍歷整個表,所以它也可以發出順序掃描。
至於為什么查詢具有與explain analyze
不同的性能,我懷疑你是正確的。 1-向您的客戶端發送15M行,以及2-嘗試顯示它們的組合將導致實際查詢之外的顯着減速。
所以你能對它做點啥?
首先,這個查詢試圖做什么? 您希望多久獲取這兩個表中的所有數據,完全未經過濾? 如果它很常見,您可能需要考慮回到需求階段並找出解決該需求的另一種方法(例如,獲取給定年份和季度的所有數據是否合理?)。 如果它不常見(例如,每日出口),則1-14分鍾可能沒問題。
其次,你應該確保你的表沒有膨脹。 如果您在表上遇到重大update
或delete
流量,則會隨着時間的推移而增加。 autovacuum守護進程可以幫助解決這個問題,但偶爾發出一個vacuum full
也會有所幫助。
第三,您可以嘗試調整數據庫配置。 在postgresql.conf
,有一些參數可用於服務器可用於磁盤高速緩存的預期RAM量,以及服務器可用於排序或連接的RAM量(在它溢出到磁盤之前)。 通過修改這些參數,您可以提高速度。
第四,您可能想要重新訪問您的架構。 您是否希望將年份和季度作為兩個單獨的列,或者您是否會更好地使用date
類型的單個列? 你想要一個text
鍵,或者你是否會更好地使用bigint
(串行或從text
列派生),這可能會更快加入? 兩個表中實際上是否需要parcel
, yr
和qtr
字段,還是它們在一個表中重復數據?
無論如何,我希望這會有所幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.