避免使用查询表在Postgres中重复数据

时间:2019-02-13 18:39:50

标签: database postgresql rdbms database-normalization

如果我有一张带有品牌和型号的已安装设备的表,其中的品牌和型号将被大量复制,但是使用各种拼写等,那么如何避免由于数据重复而浪费空间的最佳方法是什么? / p>

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数据。

源数据必须保持相同(例如,“ Panasonic”和“ PANASONIC”无法合并/校正),并且数据的规模和多样性使此操作不切实际。

我正在构想一个单独的key:value表,该表存储值,然后将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”,它将返回“ PANASONIC”的密钥,并在需要时插入)。

这种方法有什么问题(除了代码复杂性之外)?

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

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

就像@a_horse_with_no_name所说的那样,您最好创建一个模型并制作一个表,并在它们之间添加FK,然后按照您说的去做,即只保存一个新模型,或者在不存在新模型时进行制作。

我也很想拥有第三列,因此,例如,对于PANASONIC的所有可能的拼写,您既要查找输入内容的查找行,又要包含对它们可能含义的引用。这将有助于清理今后的数据。例如,当用户输入“ Panasoonic”时,您可以在用户界面中建议“您是不是松下”。

通过一次更新,存储的proc或应用代码对我们进行编码。