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

时间:2010-10-06 16:54:21

标签: postgresql database-partitioning

我有一个存储在PostgreSQL表中的巨大分区表。每个子表的id都有一个索引和一个检查约束,例如: (为清楚起见,删除了无关的deatils):

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 wiki(this page的最后一部分),这是一个已知问题,将在下一版本中修复。

是否有一个好的黑客可以使查询规划器利用max()min()查询的检查约束和子表索引?

谢谢,

亚当

3 个答案:

答案 0 :(得分: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;

否则,从那时起,会话将禁用那些访问策略。

答案 1 :(得分:1)

简短回答:没有。目前,没有办法让Postgres规划者了解某些聚合函数可以先检查子分区的约束。对于最小和最大的特定情况,它很容易证明,但对于一般的聚合,它是一个棘手的案例。

当它必须完成时,你总是可以把它写成几个分区的UNION ......

答案 2 :(得分:0)

我对postgres了解不多,但您可以尝试此查询(由于缺乏postgres查询的经验,我的查询语法可能不正确):

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

我很好奇这是否有效。