使用查找避免 Postgres 中的重复数据 Table
Avoid Duplicate Data in Postgres with Lookup Table
如果我有一个 table 的已安装设备带有 make 和 model,其中 make 和 model 会重复很多,但有各种拼写等,如何避免浪费的最佳方法space 来自数据重复?
CREATE TABLE equipment (
id integer NOT NULL,
make character varying(128),
model character varying(128),
lat double precision,
lon double precision,
created timestamp without time zone,
updated timestamp without time zone
);
这个table在现实中有更多的字段,将有数百万行,我还有其他table处于类似情况,总计约600 GB的数据。
源数据需要保持不变(即 "Panasonic" 和 "PANASONIC" 不能合并/更正),而且数据的规模和多样性无论如何都不切实际。
我正在设想一个单独的 key:value table 来存储值,然后 ID 仅存储在设备中 table,具有我仅传递值的功能它 return 是 ID(无论是查找它并 return 是 ID 还是插入它并 return 是新 ID)。
这将使 table 变成:
CREATE TABLE equipment (
id integer NOT NULL,
make integer,
model integer,
lat double precision,
lon double precision,
created timestamp without time zone,
updated timestamp without time zone
);
CREATE TABLE lookup (
id integer NOT NULL,
value character varying(128),
updated timestamp without time zone
);
与 table 的互动将是:
SELECT
id,
lookup_value(make) AS make,
lookup_value(model) AS model,
lat,
lon,
created,
updated
FROM
equipment
INSERT INTO
equipment (id, make, model, created)
VALUES
(nextval('equipment_id_seq'::regclass), lookup_value('Panasonic'), lookup_value('ABC123-G'), NOW())
查找 table 可以在各种字段和 table 之间重复使用,每个字符串值只出现一次,而 key:value 永远保持不变(从"Panasonic" 和 "PANASONIC" 不会更改 "Panasonic" 的密钥,而是 return "PANASONIC" 的密钥,如果需要则插入)。
这种方法有什么问题(除了代码复杂性)?
有没有更好的方法?
您绝不会想要这样的通用查找 table。一方面,这意味着您不能在两个 "value" 列和 ID 之间创建外键,因为无法停止 Make 最终进入 Model 的条目。
正如@a_horse_with_no_name所说,你最好创建一个模型并制作table,它们之间有FK,然后按照你说的只保存一个新模型或制作如果它还不存在。
我也很想拥有第三列,例如,对于 PANASONIC 的所有可能拼写,您既有他们输入内容的查找行,也有他们可能意思的参考。这将有助于清理未来的数据。例如,当他们输入 "Panasoonic" 时,您可以在 UI "Did you mean Panasonic" 中提出建议。
根据您的需要对我们进行编码,可以是单个更新、存储过程或应用程序代码。
如果我有一个 table 的已安装设备带有 make 和 model,其中 make 和 model 会重复很多,但有各种拼写等,如何避免浪费的最佳方法space 来自数据重复?
CREATE TABLE equipment (
id integer NOT NULL,
make character varying(128),
model character varying(128),
lat double precision,
lon double precision,
created timestamp without time zone,
updated timestamp without time zone
);
这个table在现实中有更多的字段,将有数百万行,我还有其他table处于类似情况,总计约600 GB的数据。
源数据需要保持不变(即 "Panasonic" 和 "PANASONIC" 不能合并/更正),而且数据的规模和多样性无论如何都不切实际。
我正在设想一个单独的 key:value table 来存储值,然后 ID 仅存储在设备中 table,具有我仅传递值的功能它 return 是 ID(无论是查找它并 return 是 ID 还是插入它并 return 是新 ID)。
这将使 table 变成:
CREATE TABLE equipment (
id integer NOT NULL,
make integer,
model integer,
lat double precision,
lon double precision,
created timestamp without time zone,
updated timestamp without time zone
);
CREATE TABLE lookup (
id integer NOT NULL,
value character varying(128),
updated timestamp without time zone
);
与 table 的互动将是:
SELECT
id,
lookup_value(make) AS make,
lookup_value(model) AS model,
lat,
lon,
created,
updated
FROM
equipment
INSERT INTO
equipment (id, make, model, created)
VALUES
(nextval('equipment_id_seq'::regclass), lookup_value('Panasonic'), lookup_value('ABC123-G'), NOW())
查找 table 可以在各种字段和 table 之间重复使用,每个字符串值只出现一次,而 key:value 永远保持不变(从"Panasonic" 和 "PANASONIC" 不会更改 "Panasonic" 的密钥,而是 return "PANASONIC" 的密钥,如果需要则插入)。
这种方法有什么问题(除了代码复杂性)?
有没有更好的方法?
您绝不会想要这样的通用查找 table。一方面,这意味着您不能在两个 "value" 列和 ID 之间创建外键,因为无法停止 Make 最终进入 Model 的条目。
正如@a_horse_with_no_name所说,你最好创建一个模型并制作table,它们之间有FK,然后按照你说的只保存一个新模型或制作如果它还不存在。
我也很想拥有第三列,例如,对于 PANASONIC 的所有可能拼写,您既有他们输入内容的查找行,也有他们可能意思的参考。这将有助于清理未来的数据。例如,当他们输入 "Panasoonic" 时,您可以在 UI "Did you mean Panasonic" 中提出建议。
根据您的需要对我们进行编码,可以是单个更新、存储过程或应用程序代码。