2010-10-06 52 views
0

我有一個巨大的分區表存儲在PostgreSQL表。每個子表對其id具有索引和檢查約束,例如, (爲了清楚起見移除無關deatils):PostgreSQL +表分區:低效max()和min()

Master table: points 
    Column  |   Type    |  Modifiers   
---------------+-----------------------------+------------------------ 
id   | bigint      | 
creation_time | timestamp without time zone | 
the_geom  | geometry     | 


Sub-table points_01 
    Column  |   Type    |  Modifiers   
---------------+-----------------------------+------------------------- 
    id   | bigint      | 
creation_time | timestamp without time zone | 
the_geom  | geometry     | 

Indexes: 
    "points_01_pkey" PRIMARY KEY, btree (id) 
    "points_01_creation_time_idx" btree (creation_time) 
    "points_01_the_geom_idx" gist (the_geom) CLUSTER 
Check constraints: 
    "enforce_srid_the_geom" CHECK (srid(the_geom) = 4326) 
    "id_gps_points_2010_08_22__14_47_04_check" 
       CHECK (id >= 1000000::bigint AND id <= 2000000::bigint) 

現在,

SELECT max(id) FROM points_01 

是即時的,但:

SELECT max(id) FROM points 

這是points_01 .. points_60一個主表,並應使用需要很少的時間檢查約束,需要一個多小時,因爲查詢規劃器不利用檢查約束。

根據PostgreSQL維基(this page的最後部分),這是一個已知問題,將在下一個版本中解決。

是否有一個很好的黑客會使查詢規劃器利用檢查約束和子表的索引max()min()查詢?

感謝,

亞當

+0

你能展示你的執行計劃嗎? – 2010-10-06 16:57:35

回答

1

簡短回答:不。現在,無法讓Postgres規劃人員明白,某些聚合函數可以首先檢查子分區上的約束條件。對於最小和最大值的特定情況,它很容易證明,但對於總體來說,它是一個艱難的情況。

你總是可以寫爲多個分區的UNION時,它只是做...

1

我不知道這是否會工作,但你可以試試這個:

對於那次會議上,你可以禁用所有的訪問策略,但索引的:

db=> set enable_seqscan = off; 
db=> set enable_tidscan = off; 
db=> -- your query goes here 

這樣,只有bitmapscanindexscan將被啓用。 PostgreSQL將別無選擇,只能使用索引來訪問表中的數據。

運行查詢後,記得做重新啓用seqscantidscan

db=> set enable_seqscan = on; 
db=> set enable_tidscan = on; 

否則,這些訪問策略將用於從該點上的會話被禁用。

+0

這些設置是特定於會話還是全局的? – 2010-10-06 17:38:27

+1

您可以通過更改「postgresql.conf」來使它們成爲全局的。但我強烈勸阻你這樣做。如果你使用** set **,他們將會是會話特定的。正如我在答覆中所述,禁用seqscan和tidscan **僅針對該查詢**並立即重新啓用它們。 – 2010-10-06 18:01:44

0

我不知道很多關於Postgres的,但你可能可以試試這個查詢(我的查詢語法可能由於缺乏postgres查詢經驗):

SELECT id FROM points a WHERE id > ALL (SELECT id FROM x WHERE x.id != a.id) 

我很好奇,如果這個工程。