Joh*_*and 2 postgresql database-design best-practices primary-key
假设您有一张桌子groups
和一张桌子item
。每个项目都属于一个组。它是该群体的固有组成部分。一个项目不能存在于一个组之外,也不能移动到另一个组中。
当试图决定item
表的主键时,我应该使用什么?
我应该像这样组成一个人工全局序列键:
CREATE TABLE items
(
item serial PRIMARY KEY,
group integer NOT NULL REFERENCES groups(group),
);
Run Code Online (Sandbox Code Playgroud)
...或者我应该使用复合键和每组项目序列,如下所示:
CREATE TABLE items
(
group integer NOT NULL REFERENCES groups(group),
item integer NOT NULL,
PRIMARY KEY(group, item)
);
Run Code Online (Sandbox Code Playgroud)
我更倾向于第二种解决方案的原因是帖子 URL 将始终显示组和项目,因此将它们都作为复合主键是有意义的。在第一种解决方案的情况下,URL 包含多余的信息,因为组 ID 已经可以单独从项目 ID 中推导出来。但是,URL 结构是给定的,不能更改。
第二种解决方案的缺点是您必须管理每个组的序列(即每个组的每个项目整数应从 0 开始)。
在最佳实践、规范化和性能方面哪个更好?或者这只是品味问题?
这在很大程度上是品味和风格的问题。更重要的是:特定的要求和一致的约定。但是,这个通用建议有很好的理由:
CREATE TABLE item (
item_id serial PRIMARY KEY,
grp_id integer NOT NULL REFERENCES grp(grp_id)
);
Run Code Online (Sandbox Code Playgroud)
如果你有一个item_id
,最好让它独一无二,最好是一个代理主键,对数字本身没有任何特定含义。这很便宜而且用途广泛。每组(非per-row
)连续剧通常是昂贵的、毫无意义的努力。如果您希望每组无间隙编号,请添加某种等级列或row_number()
在视图中使用。如果可以避免,请不要依赖无间隙编号。迟早你将不得不删除或移动项目。
具有遵循命名约定的单列主键便于维护(除非您有明显的自然pk)。
不要group
用作标识符。它是一个保留字。即使这些只是象征性的名称。
如果您通过 查询grp_id
,请添加另一个索引:
CREATE INDEX item_foo_idx ON item (grp_id, item_id);
Run Code Online (Sandbox Code Playgroud)
您可能希望将其UNIQUE INDEX
作为文档,但这是多余的,因为item_id
它已经是独一无二的。对于两个整数列,多列索引与 just 上的索引一样大,grp_id
并且似乎在某些用例中您需要这两列,因此有可能使用覆盖索引。这应该是最佳的。这里有更多理由:
复合索引是否也适用于第一个字段的查询?
归档时间: |
|
查看次数: |
1701 次 |
最近记录: |