带模数的分区表,如何索引? PostgreSQL

Posted

技术标签:

【中文标题】带模数的分区表,如何索引? PostgreSQL【英文标题】:Partition table with modulus, how to Index? PostgreSQL 【发布时间】:2016-08-25 12:27:07 【问题描述】:

情况

我在 PostgreSQL 9.5 中有一个数据库,用于按时间存储对象位置。

我有一个名为“位置”的主表,其中包含列(仅相关):

position_id position_timestamp object_id

在 object_id 上划分为 100 个子表,条件为:

CREATE TABLE position_object_id_00
( CHECK object_id%100 = 0 ) 
INHERITS ( position );

对于其他孩子等等。我用模数关系进行分区以平均分配对象。 每个孩子都在 position_id 和 object_id(两个不同的索引)上建立索引。

问题

当我通过 ID 查找对象时,Postgres 会对每个子表运行索引扫描:

EXPLAIN ANALYZE
SELECT * 
FROM position
WHERE object_id = 3

"Append  (cost=0.43..35925.81 rows=51119 width=97) (actual time=0.109..46.362 rows=52418 loops=1)"
"  ->  Index Scan using position_object_id_position_timestamp_idx on position  (cost=0.43..34742.00 rows=24811 width=97) (actual time=0.108..15.367 rows=26209 loops=1)"
"        Index Cond: (object_id = 3)"
"  ->  Index Scan using position_object_id_00_object_id_idx on position_object_id_00  (cost=0.29..4.30 rows=1 width=97) (actual time=0.102..0.102 rows=0 loops=1)"
"        Index Cond: (object_id = 3)"
"  ->  Index Scan using position_object_id_01_object_id_idx on position_object_id_01  (cost=0.29..4.30 rows=1 width=97) (actual time=0.065..0.065 rows=0 loops=1)"
"        Index Cond: (object_id = 3)"
"  ->  Index Scan using position_object_id_02_object_id_idx on position_object_id_02  (cost=0.29..4.30 rows=1 width=97) (actual time=0.069..0.069 rows=0 loops=1)"
"        Index Cond: (object_id = 3)"
"  ->  Seq Scan on position_object_id_03  (cost=0.00..757.61 rows=26209 width=97) (actual time=0.030..5.337 rows=26209 loops=1)"
"        Filter: (object_id = 3)"
"  ->  Index Scan using position_object_id_04_object_id_idx on position_object_id_04  (cost=0.29..4.30 rows=1 width=97) (actual time=0.067..0.067 rows=0 loops=1)"
"        Index Cond: (object_id = 3)"

[...]

除了我的主表(第一行)中有数据(请参阅有关该主题的主题Before and After trigger on the same event? Fill a child table PostgreSQL)之外,Postgres 不会“识别”分区的检查条件并在每个子表上查找 ID table,而table position_object_id_03中只有对应的id。

是否有一种特殊的索引方式可以直接知道要查看哪个表?

【问题讨论】:

【参考方案1】:

Postgres 不能自动将object_id = 3 的知识应用于检查约束,决定3 % 100 = 3 并选择相应的分区。提示 postgres 选择哪个分区的唯一方法是在查询中显式使用检查约束中的表达式,例如:

SELECT * FROM position WHERE object_id = 3 AND object_id % 100 = 3;

顺便说一句,我们正在开发一个用于分区的开源扩展 (pg_pathman),它内置了对哈希分区的支持,它会自动理解 object_id = 3 对应于某个分区。请检查一下。

【讨论】:

感谢您的回答。我也有一个字段“object_partition”,它将存储object_id % 100,以便我们可以查询object_id = sth AND object_partition = sth%100。这很相似:)

以上是关于带模数的分区表,如何索引? PostgreSQL的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server中的索引结构与疑惑

大牛手把手带你!mysql详细教程

DB2 分区表的效率问题及如何建立索引

一文带你搞懂 MySQL 中的分区!

oracle表分区和索引分区

Oracle12c中性能优化&功能增强新特性之全局索引DROP和TRUNCATE 分区的异步维护