2010-02-10 68 views
10

我刚刚重组了我的数据库,使用PostgreSQL 8.2中的partitioning。现在我遇到查询性能问题:多分区Postgres表的高效查询

SELECT * 
FROM my_table 
WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11' 
ORDER BY id DESC 
LIMIT 100; 

表中有4500万行。在分区之前,这将使用反向索引扫描并在达到极限时立即停止。

分区后(在time_stamp范围内),Postgres会对主表和相关分区执行完整索引扫描,并合并结果,对它们进行排序,然后应用限制。这需要太长时间。

我可以解决这个问题:

SELECT * FROM (
    SELECT * 
    FROM my_table_part_a 
    WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11' 
    ORDER BY id DESC 
    LIMIT 100) t 
UNION ALL 
SELECT * FROM (
    SELECT * 
    FROM my_table_part_b 
    WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11' 
    ORDER BY id DESC 
    LIMIT 100) t 
UNION ALL 
    ... and so on ... 
ORDER BY id DESC 
LIMIT 100 

这跑得快。时间戳超出范围的分区甚至不包括在查询计划中。

我的问题是:是否有某种暗示或语法,我可以在Postgres的8.2用于阻止查询筹办者通过扫描整个表,但仍使用简单的语法,只是指主表?

基本上,我是否可以避免动态构建每个正在被定义的分区的UNION查询的痛苦?

编辑:我已经启用(感谢@Vinko Vrsalovic)

+1

8.2?真?在做任何事情之前,你应该考虑升级到支持(和当前)的Postgres版本(9.2是当前的版本) – 2013-04-01 15:57:50

回答

3

有你(你链接到文档中的第5.9.4节)试图约束排除constraint_exclusion

约束排除是查询 优化技术,其改进了以上述方式定义的分区表 的性能 。作为一个例子:

SET constraint_exclusion = on; 
SELECT count(*) FROM measurement WHERE logdate >= DATE '2006-01-01'; 

没有 约束排除,上述查询 将扫描每个 测量表的分区。启用约束 排除,规划将 检查每个 分区的限制,并试图证明 分区不需要被扫描,因为 它不能包含满足 查询的WHERE子句中的任何行。当计划者可以证明这一点时,它会从查询计划中排除 分区。

您可以使用EXPLAIN命令 显示计划 与constraint_exclusion on和 计划之间的差异。

+0

是的,我已经开启了约束排除。不幸的是,主表(总是空的)总是包含在查询中,因为它不可能对它应用CHECK约束(至少在8.2中)。这意味着查询中始终包含至少两个表 – 2010-02-10 12:48:52

4

我有一个类似的问题,我可以通过在WHERE中投射条件来解决。 EG:(假设TIME_STAMP列timestamptz型)

WHERE time_stamp >= '2010-02-10'::timestamptz and time_stamp < '2010-02-11'::timestamptz 

此外,还要确保餐桌上的CHECK条件是指以同样的方式... EG: CHECK(TIME_STAMP < '2010-02-10' :: timestamptz)

2

我有同样的问题,并将其归结为两个原因,在我的情况:

  1. 我已经索引的列类型timestamp WITH time zone以及此列的分区约束,其类型为timestamp WITHOUT time zone

  2. 修复约束后需要所有子表的ANALYZE

编辑:知识的另一位 - 它要记住,约束排除(允许PG跳过扫描某些表根据您的划分标准)不工作是很重要的,报价:non-immutable function such as CURRENT_TIMESTAMP

我有CURRENT_DATE的请求,这是我的问题的一部分。