我需要为我的表的主键,它具有独特的(复合4列),其中之一可以是NULL?(Do I need a p

2019-06-24 07:12发布

我有一些存储产品的价格如下表(PostgreSQL 8.3版本)。 价格与其他数据库同步,基本上最下方(除了一个)字段不被我们的客户更新 - 而是下降,每刷新一次在一,而与另一股票数据库同步:

CREATE TABLE product_pricebands (
    template_sku varchar(20) NOT NULL,
    colourid integer REFERENCES colour (colourid) ON DELETE CASCADE,        
    currencyid integer NOT NULL REFERENCES currency (currencyid) ON DELETE CASCADE,
    siteid integer NOT NULL REFERENCES site (siteid) ON DELETE CASCADE,

    master_price numeric(10,2),

    my_custom_field boolean, 

    UNIQUE (template_sku, siteid, currencyid, colourid)
);

在同步,我基本上DELETE大部分数据所不同的是WHERE my_custom_field是真正的数据(如果这是真的,这意味着客户端通过自己的CMS更新这一领域,因此这个纪录不应该被丢弃)。 然后我INSERT 100S到行1000到表中,并在那里UPDATE INSERT失败(即,其中的(template_sku,SITEID,currencyid,colourid)组合已经存在)。

我的问题是 - 什么最好的做法应该在这里应用到创建一个主键? 是一个主键,甚至需要? 我想使主键=(template_sku,SITEID,currencyid,colourid) - 但colourid字段可以是NULL,并且在一个复合主键使用它是不可能的。

从我在其他论坛的帖子看,我想我已经上做得正确,并且只需要澄清:

1)我应该使用“串行”主键,以防万一我永远需要一个? 目前,我不这样做,不认为我是永远的,因为在表中的重要数据是价格和我的自定义字段,只能由(template_sku,SITEID,currencyid,colourid)组合标识。

2)由于(template_sku,SITEID,currencyid,colourid)是我将用于查询产品的价格相结合,我应该添加任何进一步的索引到我的专栏,如“template_sku”,这是一个varchar? 或者是唯一约束的良好指标已经为我的选择α

Answer 1:

我应该使用“串行”主键,以防万一我永远需要一个?

您可以轻松地添加一个串行列后,如果你需要一个:

ALTER TABLE product_pricebands ADD COLUMN id serial;

列将充满自动唯一值。 你甚至可以让它在同一个语句中的主键(如果没有定义主键,还):

ALTER TABLE product_pricebands ADD COLUMN id serial PRIMARY KEY;

如果从其它表引用的表我会建议使用这样的代理主键 ,因为它是相当笨拙四列链接。 它的方式选择也比较慢与连接。

无论哪种方式,您应该定义主键 。 包括空列唯一索引不是完全替代。 它允许重复对的组合,包括一个NULL值,因为两个空值永远不会被视为是相同的。 这可能会导致麻烦。


该colourid场可以为NULL

您可能要创建两个唯一索引 。 该组合(template_sku, siteid, currencyid, colourid)不能是PRIMARY KEY ,因为可空的colourid ,但你可以创建一个UNIQUE约束像你已经有(自动实现的指标):

ALTER TABLE product_pricebands ADD CONSTRAINT product_pricebands_uni_idx
UNIQUE (template_sku, siteid, currencyid, colourid)

该指数涵盖完美您在2提到的查询)。
创建另外一个部分唯一索引,如果你想避免“重复”与(colourid IS NULL)

CREATE UNIQUE INDEX product_pricebands_uni_null_idx
ON product_pricebands (template_sku, siteid, currencyid)
WHERE colourid IS NULL;

要覆盖所有的基地。 我在写了更多关于该技术的dba.SE相关答案 。


简单替代上述是使colourid NOT NULL和创建一个主密钥,而不是上述product_pricebands_uni_idx


此外,由于你

基本上删除大部分数据

为您的填充过程中,这将是更快地删除索引,在再充操作过程中并不需要 ,并重新创建这些之后。 它是由一个数量级从头开始建立索引,而不是逐步添加所有行得更快。

你怎么知道,使用哪些索引(需要)?

  • 测试你的查询与EXPLAIN ANALYZE
  • 或者使用内置的统计数据 。 pgAdmin发布在所选对象的单独选项卡显示的统计信息。

它也可以是更快的选择具有几排my_custom_field = TRUE到一个临时表, TRUNCATE基表和重新插入幸存者。 取决于你是否有定义的外键。 应该是这样的:

CREATE TEMP TABLE pr_tmp AS
SELECT * FROM product_pricebands WHERE my_custom_field;

TRUNCATE product_pricebands;
INSERT INTO product_pricebands SELECT * FROM pr_tmp;

这避免了大量的吸尘。



文章来源: Do I need a primary key for my table, which has a UNIQUE (composite 4-columns), one of which can be NULL?