我在PostgreSQL 8.2的分叉版本上已經適應了MPP。我試圖從兩個較大的表格中計算出一系列最佳下界的最大下界。這裏是前述方式表的例子:優化涉及一組時間最大下界的查詢PostgreSQL
Table A
|source_ip (inet type) |s_time (date type) |
------------------------------------------------
|10.50.43.200 | 2013-02-21 01:47:08 |
|10.50.43.200 | 2013-02-21 01:47:38 |
|10.50.43.200 | 2013-02-21 01:47:41 |
|10.50.43.200 | 2013-02-25 17:05:00 |
|10.50.43.200 | 2013-02-25 17:05:03 |
|10.50.43.200 | 2013-02-25 17:05:04 |
|10.50.43.200 | 2013-02-25 17:05:34 |
|10.50.43.200 | 2013-02-25 17:10:01 |
|10.50.43.200 | 2013-02-25 17:12:52 |
Table B
|source_ip (inet type) |mac (macaddr type) |l_time (date type) |
----------------------------------------------------------------------
|10.50.43.200 | 00:24:d7:99:e9:0c | 2013-02-20 22:33:47 |
|10.50.43.200 | 00:24:d7:99:e9:0c | 2013-02-20 23:07:32 |
|10.50.43.200 | 00:24:d7:99:e9:0c | 2013-02-20 23:13:04 |
|10.50.43.200 | 00:24:d7:99:e9:0c | 2013-02-21 00:02:56 |
|10.50.43.200 | 00:24:d7:99:68:14 | 2013-02-25 17:04:56 |
|10.50.43.200 | 00:24:d7:99:68:14 | 2013-02-25 17:04:59 |
|10.50.43.200 | 00:24:d7:99:68:14 | 2013-02-25 17:26:15 |
對於表A
我想加入一個附加列,那就是「最大下界」爲表B
每個時間戳的每一行。也就是說,我想要一個包含表B中所有值中的最大時間的列,並且也小於或等於表A
中的相應時間。我期待的輸出將類似於以下內容:
OUTPUT
------------------------------------------------------------
|10.50.43.200 |2013-02-21 01:47:38 |2013-02-21 00:02:56 |
|10.50.43.200 |2013-02-21 01:47:41 |2013-02-21 00:02:56 |
|10.50.43.200 |2013-02-25 17:05:00 |2013-02-25 17:04:59 |
|10.50.43.200 |2013-02-25 17:05:03 |2013-02-25 17:04:59 |
|10.50.43.200 |2013-02-25 17:05:04 |2013-02-25 17:04:59 |
|10.50.43.200 |2013-02-25 17:05:34 |2013-02-25 17:04:59 |
下面的查詢是什麼,我想出了,但我不知道,如果使用max()
聚合函數是實現這一目標的最佳方式。
所以,我的問題是 - 我們可以在不使用max()
的情況下重寫下面的查詢,以便在大型數據集(在100多萬個範圍內)更快?
SELECT a.source_ip,
a.s_Time, max(b.l_Time) AS max_time
FROM table_a AS a
INNER JOIN
table_b AS b
ON (a.source_ip = b.source_ip AND a.s_time > b.l_time)
GROUP BY a.source_ip, b.sourcemac, a.s_time
ORDER BY a.s_time asc;
這裏是解釋計劃:
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------
Gather Motion 72:1 (slice1; segments: 72) (cost=1519175930.51..1519305453.91 rows=143915 width=48)
-> HashAggregate (cost=1519175930.51..1519305453.91 rows=143915 width=48)
Group By: a.source_ip, a.s_time
-> Hash Join (cost=991681.79..1169135585.55 rows=648222862 width=23)
Hash Cond: a.source_ip = b.source_ip
Join Filter: a.s_time > b.l_time
-> Append-only Columnar Scan on a (cost=0.00..1083707.12 rows=1439149 width=15)
-> Hash (cost=487360.24..487360.24 rows=560358 width=15)
-> Seq Scan on b (cost=0.00..487360.24 rows=560358 width=15)
(9 rows)
我知道我可以哈希source_ip
-s來bigints更快的連接。我也認爲可能值得嘗試索引連接中使用的列,但我不確定最佳優化策略是什麼,並且會喜歡來自StackOverflow社區優秀專家組的任何輸入。我們也嘗試了rank()
窗口函數,但是它在我們正在使用的實現上存在問題,並且是我們測試過的這種類型的查詢性能最差的函數,所以理想的策略將有望避免任何窗口函數。
編輯:添加一個索引上source_ip
,start_yime
爲表A
和重寫使用LIMIT 1
建議在後查詢:
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------
Gather Motion 72:1 (slice2; segments: 72) (cost=1624120.24..7442384075819.75 rows=145921 width=48)
-> HashAggregate (cost=1624120.24..7442384075819.75 rows=145921 width=48)
Group By: a.src, a.start_time
-> Append-only Columnar Scan on a (cost=0.00..1098806.16 rows=1459206 width=15)
SubPlan 1
-> Limit (cost=708374.49..708374.51 rows=1 width=15)
-> Limit (cost=708374.49..708374.49 rows=1 width=15)
-> Sort (cost=708374.49..708376.35 rows=11 width=15)
Sort Key (Limit): b.source_ip, b.start_time
-> Result (cost=708339.65..708347.10 rows=11 width=15)
Filter: $0 = b.source_ip AND $1 > b.start_time
-> Materialize for deadlock safety (cost=708339.65..708347.10 rows=11 width=15)
-> Broadcast Motion 72:72 (slice1; segments: 72) (cost=0.00..708338.90 rows=11 width=15)
-> Seq Scan on b (cost=0.00..708338.90 rows=11 width=15)
什麼指數的定義? –
請將包含索引和相關部分配置參數的表結構添加到問題中。 (看起來你已經將work_mem設置爲一個非常大的值)BTW:pg-8.2是非常古老的。 – wildplasser