如何在PostgreSQL 8.3.7中使用分区表的索引?

5

我有这样一种情况,运行一个过滤分区表中索引列的查询时,会执行全表扫描。

显然,在PostgreSQL中,这是一个已知的问题,并且在这里有详细解释。

除了对每个分区执行查询,然后对所有结果执行UNION之外,是否还有更优雅的方法来解决这个问题?


请在此处向Postgres性能邮件列表询问:http://archives.postgresql.org/pgsql-performance/。 - Milen A. Radev
你所链接的那篇文章不准确,因为作者对分区并不是特别熟悉。他没有启用constraint_exclusion或在每个分区上创建索引。 - Jin Kim
我不明白为什么在跨越分区边界的查询中应该排除索引。在我的情况下,当我尝试查找每个分区中具有索引的列的非常小的一组不同值时,我发现了这个问题。在分区上选择唯一的列使用索引扫描。在父表上执行相同操作会对每个分区进行完整的表扫描,然后合并,最后排序。"select distinct column from(select union select union select ...)"比"select distinct column from parent" 快得多。有人知道为什么规划程序不做显而易见的事情吗? - ideasculptor
1个回答

11

在PostgreSQL中,索引可以良好地进行有关分区的扫描。但是,你必须正确设置所有内容才能使其正常工作,并且很容易错过http://www.postgresql.org/docs/current/static/ddl-partitioning.html中所记录的众多步骤之一。

最重要的是要认识到,为了避免顺序扫描,你必须提供足够的信息,以便PostgreSQL可以证明某些分区不可能具有你正在查找的数据; 然后跳过它们作为查询结果的潜在来源。你链接的文章指出这是顺序扫描问题的解决方案:“如果将范围约束添加到每个分区的日期字段中,则可以将此查询优化为一个循环,其中您首先查询“最新”分区,然后向后工作,直到找到一个单个值高于所有剩余分区的范围。”但并没有显示更改后会看到的改进计划。

你可能犯了一些常见的错误:

- postgresql.conf文件中的constraint_exclusion参数默认关闭。在默认情况下,你将得不到预期的结果。

-未使用CHECK创建非重叠分区,这会使规划程序无法知道每个分区中的内容。可能会错过此步骤,但仍然可以将数据正确放入正确的分区中,只是规划程序不会知道。

-没有在每个分区上放置索引,只在主表上创建了一个索引。这将使你仅获得有关相关分区的顺序扫描,因此并不像上述问题那样糟糕,但也不好。

在即将发布的PostgreSQL版本中可以更轻松地进行所有这些操作(在8.4中设置constraint_partition相当自动化,并正在努力开发某种分区设置自动化)。现在,如果你仔细遵循说明并避免所有这些问题,应该工作正常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接