高效查询多分区Postgres表

时间:2010-02-10 12:39:33

标签: sql performance postgresql partitioning

我刚刚重组了我的数据库,以便在Postgres 8.2中使用partitioning。现在我的查询性能有问题:

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查询的痛苦?

编辑:我启用了constraint_exclusion(感谢@Vinko Vrsalovic)

3 个答案:

答案 0 :(得分:5)

您是否尝试过约束排除(您链接到的文档中的第5.9.4节)

  

约束排除是一种查询   改进的优化技术   分区表的性能   以所描述的方式定义   以上。举个例子:

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

无   约束排除,上面的查询   将扫描每个分区   测量表。有约束力   排除启用,规划人员将   检查每个的约束   分区,并试图证明   不需要扫描分区,因为   它不能包含任何行会议   查询的WHERE子句。当。。。的时候   规划师可以证明这一点,但不包括在内   查询计划中的分区。

     

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

答案 1 :(得分:4)

我有一个类似的问题,我可以通过在WHERE中转换条件来修复。 EG :(假设time_stamp列是timestamptz类型)

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

另外,确保表格中的CHECK条件定义方式相同... 例如:   检查(time_stamp&lt;'2010-02-10':: timestamptz)

答案 2 :(得分:3)

我遇到了同样的问题,在我的案例中归结为两个原因:

  1. 我已将timestamp WITH time zone类型的列编入索引,并使用类型为timestamp WITHOUT time zone的此列编制分区约束。

  2. 在修复所有子表的约束ANALYZE之后。

  3. 编辑:另一点知识 - 重要的是要记住约束排除(允许PG根据您的分区标准跳过扫描某些表)不起作用,引用:{{1 }}

    我收到了non-immutable function such as CURRENT_TIMESTAMP的请求,这是我问题的一部分。