Database 使用查找表避免Postgres中的重复数据

Database 使用查找表避免Postgres中的重复数据,database,postgresql,rdbms,database-normalization,Database,Postgresql,Rdbms,Database Normalization,如果我有一个带有品牌和型号的已安装设备表,其中品牌和型号会大量重复,但拼写有多种,等等,那么如何最好地避免因数据重复而浪费空间 CREATE TABLE equipment ( id integer NOT NULL, make character varying(128), model character varying(128), lat double precision, lon double precision, created times

如果我有一个带有品牌和型号的已安装设备表,其中品牌和型号会大量重复,但拼写有多种,等等,那么如何最好地避免因数据重复而浪费空间

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
);
这个表实际上有更多的字段,将有数百万行,我还有其他类似情况的表,总共大约有600 GB的数据

源数据需要保持不变,即松下和松下不能合并/更正,而且数据的规模和多样性使其无论如何都不可行

我正在设想一个单独的键:值表,它存储值,然后ID只存储在设备表中,使用一个函数,我只传递值,它返回ID,无论它是查找并返回ID,还是插入ID并返回新ID

这将使表格变成:

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
);
与表格的交互将是:

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()) 
查找表可以在各种字段和表中重复使用,每个字符串值只出现一次,并且key:value永远保持不变从Panasonic更改而Panasonic不会更改Panasonic的key,而是返回Panasonic的key,必要时插入

除了代码复杂性之外,这种方法还有什么问题


有更好的方法吗?

您永远不会想要这样的通用查找表。首先,这意味着您不能在两个值列和ID之间创建外键,因为无法停止在模型中结束的Make条目

正如@a_horse_和_no_name所说的,您最好创建一个模型并生成一个表,在它们之间使用FK,然后按照您所说的那样,只保存一个新模型,或者如果它不存在,则生成一个表

我还希望有第三列,因此对于松下的所有可能拼写,例如,您既有输入内容的查找行,也有对其可能含义的引用。这将有助于今后清理数据。例如,你可以在用户界面中建议,当他们进入Panasoonic时,你是指Panasonic吗


在单个更新、存储过程或应用程序代码中为我们编码

这种反模式也被称为真正的查找表,并不是一个好主意。一个适当规范化的数据模型将有一个表用于模型,一个表用于make。如果make依赖于模型,那么它应该有model的外键,设备应该只引用make表。make和model行从varchar 128更改为整数。NEC North America,Inc.的数千个实例或任何将被12345取代的实例。最常用的一个表中有500000多个使用,这只是该特定品牌几十个拼写变体中的一个。因此,节省的磁盘空间将增加,这是几十个具有此类数据的字段之一;make and model只是使用的示例。是的,我们计划在第三列中添加一个整数,该整数指向要使用的替换ID,用于拼写错误、标点符号变化等。因此,理想情况下,除了一个Panasonic变体之外,其他所有变体都将,指向首选的拼写。数据库中是否有任何方法可以使用FK单独设置表,并且仍然为拼写错误设置别名?还是FK排除了这一点,它必须在应用程序中处理?我假设Make和Model是两个独立的数据集,有自己的拼写错误集。如果有一个完整的拼写列表,那么为了简单起见,您可能只需要有一个通用的NameA->NameB列表,然后在make或model表中查找NameB以获得正确的键。