0

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

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

是否有一个很好的技巧可以使查询计划器利用子表的检查约束和索引进行max()查询min()

谢谢,

亚当

4

3 回答 3

2

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

对于该会话,您可以禁用所有访问策略,但索引的策略:

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

这样,只有bitmapscan并且indexscan将被启用。PostgreSQL 将别无选择,只能使用索引来访问表上的数据。

运行查询后,请记住重新启用seqscantidscan执行以下操作:

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

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

于 2010-10-06T17:03:00.557 回答
1

简短的回答:不。在这个时间点上,没有办法让 Postgres 规划器明白一些聚合函数可以首先检查子分区的约束。对于最小值和最大值的特定情况,它相当容易证明,但对于一般的聚合,它是一个艰难的情况。

当必须完成时,您始终可以将其写为多个分区的 UNION ...

于 2010-10-06T21:56:57.777 回答
0

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

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

我很好奇这是否有效。

于 2010-10-07T16:56:37.013 回答