在处理No-SQL数据库时,这不会是一个问题,因为关系没有意义(或者至少不需要),但是当基础结构不支持No-SQL数据库时,创建标记等场景对于文章会引起一些担忧(从找到最佳实践的角度来看)。
假设我有三个表Articles
,Tags
,ArticleTags
。在这种情况下,Tag
名称必须是唯一的,因为Tags
表中的重复标记没有任何意义。将此记入帐户,我可以执行以下操作:
CREATE TABLE [Tags](
[TagId] UNIQUEIDENTIFIER ROWGRIDCOL PRIMARY KEY DEFAULT NEWSEQUENTIALID(),
[Name] NVARCHAR(50) NOT NULL UNIQUE
)
这种方法可以被视为一种标准做法。但是,由于Tags.Name
是唯一的,我还可以使用Name
列作为主键并删除TagId
列。问题是,如果我这样做并使用Tags.Name
作为主键,即使Tags
表也会被视为冗余,我只需添加一个新列,例如Tag
在ArticleTags
表中没有任何关系,如果我们想要允许用户在必要时生成新标签(丢失FK约束),这将是可以的。
但是,这会违反规范化规则吗?与标准方法(具有id和名称)相比,这是一种更好的做法吗?
答案 0 :(得分:2)
将GUID作为主要(可能有例外)是一个相当糟糕的主意。如果你有一个表,你将要进行频繁的插入,那么GUID作为主键肯定是个坏主意。
为什么呢?好吧,默认情况下,主键是在SQL Server中集群的。你可以覆盖它,但让我们坚持默认。
由于GUID可以具有较小的值,因此会导致在现有行之间进行插入。这往往会造成碎片和(很多)较慢的插入。
请注意,这甚至发生在NEWSEQUENTIALID()
。正如documentation所解释的那样:
重新启动Windows后,GUID可以从较低范围重新开始, 但仍然是全球唯一的。
如果你一次性完成所有插入,那么无关紧要。
然而,这似乎更简单:
CREATE TABLE [Tags](
[TagId] int identity(1, 1) primary key,
[Name] NVARCHAR(50) NOT NULL UNIQUE
);
以下是一些原因:
我会避免使用GUID(或其他数据库中的UUID)作为主键的习惯。我不得不放松的一个例子是我使用SparkSQL或BigQuery生成数据。但是,我认为这些工具中的错误是他们无法在大型数据集上轻松row_number()
。
至于使用Name
,我会劝阻。您可能希望在将来的某个时刻重命名标记,或者确定50个字符不够大。虽然你可以有级联外键引用,但我认为一个唯一的整数id是一种更安全的方法。此外,id会提供一些无意的信息 - 例如插入表中的最后一个标记。