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

时间:2016-08-25 12:27:08

标签: postgresql indexing partitioning modulus

场合

我在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,而表position_object_id_03中只有相应的id。

是否有特定的索引方式,以便直接知道要查找哪个表?

1 个答案:

答案 0 :(得分: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对应于某个分区。请检查一下。