在我的遗留数据库(Postgres 9.1)中,我有几个包含各种文档的表格(让我们说它们是父表'表格)。 此外,还有一个包含这些文档的各种参数的表格:
create table params (
kind integer,
docid integer,
parname text,
parvalue text,
constraint params_pk primary key (kind, docid, parname));
一个文档可能有很多(parname,parvalue)对。 由于 kind 指向不同的表,因此不能将其用作外键。
由于 params 仅用于打印文档,因此多年来一直运作良好。 现在这个表包含5百万行,并且还需要数据用于其他目的。 所以现在是更新这个模型的时候了。
基本上 params 为文档插入一次,很少更新。它们将作为一个整体阅读(对于文档)。无需搜索特定的 parname 。
我有三个想法:
变体A. 根据父表将表 params 拆分为多个表,并使用 docid 作为外键。
变种B. 将表 params 拆分为变体A,并将(parname,parvalue)存储为hstore。
变体C. 在每个父表中添加一个hstore字段,并忘记其他表。
我没有使用hstore的经验。 每种变体的缺点和优点是什么?你会选哪一个?可以用一些奇怪的东西让我感到困惑吗?
答案 0 :(得分:3)
如果您说需要使用文档获取字段,那么Denormalized hstore variant更好,因为服务器将能够从磁盘上的单个位置获取整个文档,而不是使用多个位置来索引连接文档与田地。我用hstore看到的唯一问题是一种有点不同寻常的语法。使用JSON可能更容易。 PostgreSQL 9.4将对(indexed) binary JSON提供出色的支持。 hstore作者使用二进制JSON是recommended,BTW。
因此,计划可能是在9.3中使用json
列,然后在9.4中将其转换为jsonb
。
答案 1 :(得分:2)
我投票支持第三种选择。表越少,睡眠越好。
Hstore是为一级参数列表而发明的。它稳定,快速,简单,完全符合您的需求。前段时间我有类似的任务。我写了一个汇总以便于转换。
create or replace function hstore_add(hstore, text, text)
returns hstore language plpgsql
as $$
begin
return case
when $1 isnull then hstore($2, $3)
else $1 || hstore($2, $3) end;
end $$;
create aggregate hstore_agg (text, text) (
sfunc = hstore_add,
stype = hstore
);
我认为这可以节省你的时间。
select kind, docid, hstore_agg(parname, parvalue)
from params
group by 1, 2
order by 1, 2;