Bre*_*ias 5 t-sql sql-server performance foreign-keys
“创建表”语法显然不允许我指定聚集外键约束。换句话说,这是非法的:
--keyword CLUSTERED must be removed before this will execute...
CREATE TABLE [Content](
[ID] [int] NOT NULL CONSTRAINT PK_Content_ID PRIMARY KEY,
ContentDefID int NOT NULL CONSTRAINT FK_Plugin_ContentDef FOREIGN KEY CLUSTERED REFERENCES ContentDef(ID)
)
GO
Run Code Online (Sandbox Code Playgroud)
但我不明白为什么这是非法的。ISTM 认为聚集外键将有助于分页查找的性能。换句话说,“给我父 ID 20 的子项 80 到 140”。
这有什么道理吗?
根据 Oded 和 Tvanfosson 的反馈,我发现以下方法有效:
CREATE TABLE [Content](
[ID] [int] NOT NULL CONSTRAINT PK_Content_ID PRIMARY KEY,
ContentDefID int NOT NULL UNIQUE CLUSTERED CONSTRAINT FK_ContentDefContent FOREIGN KEY REFERENCES ContentDef(ID)
)
GO
Run Code Online (Sandbox Code Playgroud)
但上述造成的问题多于其解决的问题。首先,“唯一”外键迫使我的关系成为一对一,这是我不想要的。其次,这之所以有效,是因为它代表了两个单独约束的创建,而不是单个聚集外键。
但这次调查让我更接近我的答案。显然,聚集索引必须是唯一的,如此处所述。引用:
如果聚集索引不是唯一索引,SQL Server 会通过添加称为唯一符的内部生成的值来使任何重复键唯一
特别是,我认为这个答案涵盖了它。
正如其他人所解释的,聚集索引不必是主键,但它必须是唯一的,或者 SQL-Server 向其添加一个(未显示)UNIQUIFIER列。
为了避免这种情况,您可以通过将主键列显式添加到聚集索引来使聚集索引唯一,如下所示。然后,该索引将可供外键约束使用(以及查询,例如连接两个表)。
请注意,正如 @Martin Smith 所解释的,CONSTRAINT和的概念INDEX是不同的。不同的 DBMS 以不同的方式实现这些。SQL-Server 会自动为某些约束创建索引,但不会为外键约束创建索引。但建议有一个约束可以使用的索引(在引用表中删除或更新时):
CREATE TABLE Content(
ID int NOT NULL,
ContentDefID int NOT NULL,
CONSTRAINT PK_Content_ID
PRIMARY KEY NONCLUSTERED (ID),
CONSTRAINT CI_Content
UNIQUE CLUSTERED (ContentDefID, ID),
CONSTRAINT FK_Plugin_ContentDef
FOREIGN KEY (ContentDefID) REFERENCES ContentDef(ID)
) ;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9539 次 |
| 最近记录: |