我有这种情况,运行一个按分区表中的索引列过滤的查询,执行全表扫描。
显然,这是postgresql中的一个已知问题,详细解释了here。
除了对每个分区执行查询,然后对所有结果执行UNION之外,还有更优雅的方法吗?
答案 0 :(得分:10)
索引工作得很好,只能对PostgreSQL中的相关分区进行扫描。但是,您必须正确设置所有内容才能使其正常工作,并且很容易错过http://www.postgresql.org/docs/current/static/ddl-partitioning.html中记录的长列表中的一步
要实现的主要事情是,为了避免顺序扫描,您必须向PostgreSQL提供足够的信息,以便它可以证明某些分区不能拥有您正在寻找的数据;然后将它们作为查询结果的潜在来源跳过。您链接的文章指出这是seq扫描问题的解决方案:“如果您将范围约束添加到每个分区的日期字段,可以将此查询优化为循环,您首先查询”最新“分区并工作向后,直到找到一个高于所有剩余分区范围的单个值。“ - 但不会显示您在更改后看到的改进计划。
您可能犯过的一些常见错误:
- 默认情况下,postgresql.conf文件中的constraint_exclusion参数处于关闭状态。有了这个默认值,你就无法得到你期望的结果。
- 不要使用CHECK创建非重叠的分区,这样可以防止计划者知道每个分区内部的内容。可能会错过这一步,但仍然可以正确地将数据放入正确的分区,规划人员就不会知道这一点。
-Did没有在每个分区上放置索引,只在主表上创建了一个索引。这将使您在相关分区上进行顺序扫描,因此不会像上面那样糟糕但也不好。
在即将发布的PostgreSQL版本中,有一些工作可以使这一切变得更加容易(在8.4中设置constraint_partition是相当自动的,并且正在使用某种分区设置自动化)。现在,如果你仔细遵循说明并避免所有这些问题,它应该有效。