高效查询多分区Postgres表

Adr*_*onk 11 sql postgresql performance partitioning

我刚刚重构了我的数据库,以便在Postgres 8.2中使用分区.现在我的查询性能有问题:

SELECT *
FROM my_table
WHERE time_stamp >= '2010-02-10' and time_stamp < '2010-02-11'
ORDER BY id DESC
LIMIT 100;
Run Code Online (Sandbox Code Playgroud)

表中有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
Run Code Online (Sandbox Code Playgroud)

这很快就会运行.时间戳超出范围的分区甚至不包括在查询计划中.

我的问题是:我是否可以在Postgres 8.2中使用一些提示或语法来阻止查询规划器扫描整个表但仍使用仅引用主表的简单语法?

基本上,我可以避免在当前定义的每个分区上动态构建大型UNION查询的痛苦吗?

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

小智 6

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

WHERE time_stamp >= '2010-02-10'::timestamptz and time_stamp < '2010-02-11'::timestamptz
Run Code Online (Sandbox Code Playgroud)

另外,请确保表上的 CHECK 条件以相同的方式定义... EG: CHECK (time_stamp < '2010-02-10'::timestamptz)


Vin*_*vic 5

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

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

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

在没有约束排除的情况下,以上查询将扫描测量表的每个分区。启用约束排除后,计划人员将检查每个分区的约束,并尝试证明不需要扫描该分区,因为该分区不能包含满足查询的WHERE子句的任何行。当计划者可以证明这一点时,它将从查询计划中排除该分区。

您可以使用EXPLAIN命令显示启用constraint_exclusion的计划与禁用计划的区别。