假设我们有下表:
我有以下对象:
struct Tick = {
country string
region string
type string
spec map string -> int # {v1: n1, v2:n2}
t timestamp
}
我想将这些对象存储在 Posgresql 9.4 中。将有数百万。 90%的查询将涉及:
type
country
/ region
(两者,一人或全部)的组合t
范围(大多数只是t > tx
)以上所有查询组合均匀分布。 然后大约5%将另外涉及检查规范属性:存在或范围。
在Postgresql 9.4中编码此类对象的最佳方法是什么?应该创建哪个索引?
很少有想法:
encoded = "type;country;v1:n1;v2:n2"
。那么,是否可以制作复合索引(t, encoded)
,这将允许t
上的范围查询和encoded
上的regexp查询?在这种方法中,我们忽略了索引中的规范范围检查,jsonb
中的所有内容。那么,是否可以在某些jsonb属性上进行索引范围查询? [编辑]
广告。 1.可以将这些值放在一个字符串中,而不是将它们放在一个表(tab = {type, country, v1+n1, ...}
)中,并使用btree_gini扩展名创建gin索引:gin (t timestamp_ops, tab _text_ops)
。
答案 0 :(得分:2)
保持简单。使用传统表格和复合索引。
我会看到类似的东西:
CREATE OR REPLACE TABLE blah (
country text,
region text,
type text,
spec json,
t timestamp not null
);
那里没有明显的候选键,因此您可能还需要合成主键。
然后在数据上只有一个或多个复合索引,例如
CREATE INDEX blah_t_country_region_idx
ON blah(t, type, country, region);
列的顺序很重要;如果所有查询都使用所有列,它应该从大多数选择到最小选择。否则,您应该首先放置大多数查询首先使用的列。
您可以创建多个索引。 PostgreSQL有时也可以为单个查询组合多个索引。
请记住,每个索引都有插入/更新的成本,并且还使用磁盘空间。
一个选项可能是:
CREATE INDEX blah_t_country_region_idx
ON blah(t, type);
然后在country
和region
上分隔索引。或多个复合索引,一个在t +类型+国家,一个在t +类型+区域,一个在两者上。这完全取决于您愿意支付多少磁盘空间和I / O成本,以及您的确切查询模式。
在不知道查询模式和查询explain
数据的情况下建议更详细的策略并不切合实际。
BTW,根据数据源等,您可能希望将国家和地区外键设置为查找表,而不是存储文字字符串。