ris*_*ijd 9 postgresql indexing null database-design primary-key
我有下表(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)
);
Run Code Online (Sandbox Code Playgroud)
在同步上,我基本上删除了上面的大部分数据,除了数据WHERE my_custom_field为TRUE(如果它为TRUE,则表示客户端通过其CMS更新了该字段,因此不应删除此记录).然后我将100s到1000s的行插入到表中,并且INSERT失败的UPDATE(即(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?或者UNIQUE约束是否已成为我的SELECT的良好索引?
Erw*_*ter 11
我是否应该使用"串行"主键以防我需要?
如果需要,可以稍后轻松添加一个串行列:
ALTER TABLE product_pricebands ADD COLUMN id serial;
Run Code Online (Sandbox Code Playgroud)
该列将自动填充唯一值.您甚至可以将它作为同一语句中的主键(如果尚未定义主键):
ALTER TABLE product_pricebands ADD COLUMN id serial PRIMARY KEY;
Run Code Online (Sandbox Code Playgroud)
如果您从其他表中引用该表,我建议使用这样的代理主键,因为链接四列是相当笨重的.在带有JOIN的SELECT中它也较慢.
无论哪种方式,您都应该定义主键.包含可空列的UNIQUE索引不是完全替换.它允许复制包括NULL值的组合,因为两个NULL值永远不会被认为是相同的.这可能会导致麻烦.
如
colourid字段可以为NULL
您可能想要创建两个唯一索引.由于(template_sku, siteid, currencyid, colourid)可以PRIMARY KEY为空colourid,组合不能是a ,但是你可以创建一个UNIQUE像你已经拥有的约束(自动实现索引):
ALTER TABLE product_pricebands ADD CONSTRAINT product_pricebands_uni_idx
UNIQUE (template_sku, siteid, currencyid, colourid)
Run Code Online (Sandbox Code Playgroud)
该索引完美地涵盖了您在2)中提到的查询.
如果要避免"重复",请另外创建一个部分唯一索引(colourid IS NULL):
CREATE UNIQUE INDEX product_pricebands_uni_null_idx
ON product_pricebands (template_sku, siteid, currencyid)
WHERE colourid IS NULL;
Run Code Online (Sandbox Code Playgroud)
涵盖所有基地.我在dba.SE的相关答案中写了更多关于该技术的内容.
上面的简单替代方法是使colouridNOT NULL和创建主键而不是上面的键product_pricebands_uni_idx.
还有,就像你一样
基本上删除了大部分数据
对于您的重新填充操作,删除索引会更快,在重新填充操作期间不需要,并在之后重新创建.从头开始构建索引比以递增方式添加所有行更快一个数量级.
你怎么知道,使用哪些索引(需要)?
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;
Run Code Online (Sandbox Code Playgroud)
这避免了大量的吸尘.
| 归档时间: |
|
| 查看次数: |
7369 次 |
| 最近记录: |