我有其存储柱receiver
的数据库,以表示该数据涉及(例如“查理”)的帐户。这然而导致吨数据的复制的,作为一组数据的可产生3个单独的行,其中所述唯一的区别是receiver
柱。
|---------------------|------------------||---------------------|------------------|
| Receiver | Event || Date | Location |
|---------------------|------------------||---------------------|------------------|
| Alpha | 3 || 12 | USA |
|---------------------|------------------||---------------------|------------------|
| Bravo | 3 || 12 | USA |
|---------------------|------------------||---------------------|------------------|
| Charlie | 3 || 12 | USA |
|---------------------|------------------||---------------------|------------------|
而重新设计数据库中,我使用具有GIN索引,而不是在接收机当前B树索引的阵列考虑。我提出了新的表是这样的:
|-------------------------------|------------------||------------------|-------------------|
| Receivers | Event || Date | Location |
|-------------------------------|------------------||------------------|-------------------|
| ["Alpha", "Bravo", "Charlie"] | 3 || 12 | USA |
|-------------------------------|------------------||------------------|-------------------|
所有查询的95%,目前的形式是:SELECT * FROM table WHERE Receiver = Alpha
此外,该表目前包含超过4个十亿行,这将削减下来,以在2个十亿行。
哪种选择更有效?
你不应该使用数组,而是一个标准化的数据模型,其中event
和receiver
是两个不同的表。表之间的关系应该通过receiver
外键约束来实现。
这些表是这样的:
CREATE TABLE occurrence (
occurrence_id bigint PRIMARY KEY,
event integer NOT NULL,
date integer NOT NULL,
location text NOT NULL
);
CREATE TABLE receiver (
receiver_id bigint PRIMARY KEY,
receiver_name text NOT NULL
);
CREATE TABLE log_entry (
occurrence_id bigint NOT NULL REFERENCES occurrence,
receiver_id bigint NOT NULL REFERENCES receiver,
PRIMARY KEY (occurrence_id, receiver_id)
);
日志条目引用事件发生和接收器。
你会像查询
SELECT r.receiver_name,
o.event,
o.date,
o.location
FROM occurrence AS o
JOIN log_entry AS l USING (occurrence_id)
JOIN receiver AS r USING (receiver_id)
WHERE /* your conditions */;