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()
查询?
感谢,
亚当
简短回答:不。现在,无法让Postgres规划人员明白,某些聚合函数可以首先检查子分区上的约束条件。对于最小和最大值的特定情况,它很容易证明,但对于总体来说,它是一个艰难的情况。
你总是可以写为多个分区的UNION时,它只是做...
我不知道这是否会工作,但你可以试试这个:
对于那次会议上,你可以禁用所有的访问策略,但索引的:
db=> set enable_seqscan = off;
db=> set enable_tidscan = off;
db=> -- your query goes here
这样,只有bitmapscan
和indexscan
将被启用。 PostgreSQL将别无选择,只能使用索引来访问表中的数据。
运行查询后,记得做重新启用seqscan
和tidscan
:
db=> set enable_seqscan = on;
db=> set enable_tidscan = on;
否则,这些访问策略将用于从该点上的会话被禁用。
这些设置是特定于会话还是全局的? – 2010-10-06 17:38:27
您可以通过更改“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)
我很好奇,如果这个工程。
你能展示你的执行计划吗? – 2010-10-06 16:57:35