PostgreSQL +表分区:低效max()和min()

问题描述:

我有一个巨大的分区表存储在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

简短回答:不。现在,无法让Postgres规划人员明白,某些聚合函数可以首先检查子分区上的约束条件。对于最小和最大值的特定情况,它很容易证明,但对于总体来说,它是一个艰难的情况。

你总是可以写为多个分区的UNION时,它只是做...

我不知道这是否会工作,但你可以试试这个:

对于那次会议上,你可以禁用所有的访问策略,但索引的:

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

我不知道很多关于Postgres的,但你可能可以试试这个查询(我的查询语法可能由于缺乏postgres查询经验):

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

我很好奇,如果这个工程。