我有一个数据库,其中存储一列receiver
,以表示该数据所涉及的帐户(例如“ Charlie”)。但是,这导致大量数据重复,因为一组数据可能会创建3个单独的行,唯一的区别是receiver
列。
|---------------------|------------------||---------------------|------------------|
| Receiver | Event || Date | Location |
|---------------------|------------------||---------------------|------------------|
| Alpha | 3 || 12 | USA |
|---------------------|------------------||---------------------|------------------|
| Bravo | 3 || 12 | USA |
|---------------------|------------------||---------------------|------------------|
| Charlie | 3 || 12 | USA |
|---------------------|------------------||---------------------|------------------|
在重新设计数据库时,我考虑过使用带有GIN索引的数组,而不是接收器上当前的B-Tree索引。我建议的新表将如下所示:
|-------------------------------|------------------||------------------|-------------------|
| Receivers | Event || Date | Location |
|-------------------------------|------------------||------------------|-------------------|
| ["Alpha", "Bravo", "Charlie"] | 3 || 12 | USA |
|-------------------------------|------------------||------------------|-------------------|
当前所有查询中的95%的格式为:SELECT * FROM table WHERE Receiver = Alpha
此外,该表当前包含超过40亿行,这将使其减少到不足20亿行。
哪个选项更有效?
答案 0 :(得分:0)
您不应该使用数组,而是使用规范化的数据模型,其中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 */;