何时使用唯一组合键?

Fre*_*eya 6 database-design unique-constraint

在创建数据库结构时,我倾向于为每组需要唯一的数据创建唯一的复合键。在它们旁边我通常使用主键(通常是 INT AI id),除非复合键确实足以识别记录。

一方面,好处是我可以避免插入“坏记录”。是否存在这些密钥的使用变得过多或数据库设计不佳的迹象?

MDC*_*CCL 10

如果目的是建立关系数据库,那么目标应该是在数据库布局中反映相关业务环境的信息特征,所以简短的回答是:

每当考虑中的表的每一行都必须通过一个或多个列组合的值进行唯一区分时,数据库设计者必须定义一个或多个复合键

这样,数据库设计者负责 (1) 识别该业务上下文需求和 (2) 声明相应的多列 KEY 约束。

如您所知,他或她有责任 (i) 识别和 (ii)在必要时也声明单列 KEY 。

因此,一般程序应该始终非常仔细地分析每个特定情况,检查赋予每个单独表和列的含义,并考虑到它们与整个数据库布局的所有互连。

系统控制的替代品的额外列

通过非常仔细地分析每个特定情况,我们也可以确定非常具体的情况,除了声明一个或多个单列或多列自然键(根据需要),表可能会受益于包含额外的柱保留系统控制的替代物一个代理人为了简洁,这被实现,例如,通过IDENTITY在Microsoft SQL Server属性或AUTO_INCREMENT在MySQL属性),作为这样的伪影是在所有时间附接元件,其需要补充管理任务(例如,它经常需要一个陪伴 INDEX 在物理级别,及其所有含义)。

上面提出的观点是相关的,因为根据我对以下问题摘录“我通常使用主键(通常是 INT AI id)”的解释,您所描述的正是保留代理项的列。

在这方面,由于优化数据库平台资源(数据库管理系统、硬件等)的使用至关重要,必须提到的是,数据库从业者只有在有正当理由的情况下才应采用任何类型的技术添加。重要数据库中表示的业务上下文的特征。

包含代理的列在某种程度上可以作为相应自然 KEY 值的“替代品”有时会有所帮助,例如,在以下表格中使用它时:

  • 表示位于相关概念数据层次结构顶层的实体类型。
  • 具有和/或重的自然 KEY ,因此防止通过 FOREIGN KEY (FK) 约束从其他表引用它们可能很有用。

以这种方式,对包含物理上字节数更轻的值的列进行 FK 引用(与对相对较大的列组合的引用和/或对设置为类型和大小的列的引用相比)由于支持相关逻辑级别定义的物理级别脚手架的减少,因此对例如磁盘空间和内存消耗产生影响。

多列键的一般优点

数据操作

在代表(概念)实体类型的表属于感兴趣的业务上下文的数据层次结构的较低层的情况下,复合主键 (PK) 往往更有效,因为它们通常在(逻辑)中被调用SELECT 操作包括指向上述层次结构中较高层的表的 PK 的列,而通常不涉及具有代理值的列。

沿着这些思路,使用复合 PK 通常可以方便地避免不必要的 JOIN(这并不意味着 JOIN 操作符是一个糟糕的工具,恰恰相反,它是一个必不可少的、优雅的和强大的数据工具推导在正确的设置下运行非常快),并且与之前提出的平台资源优化一致,应该采用和提供尽可能高效的数据操作机制。

例如,假设逻辑级 SQL-DDL 布局如下所示:

--
-- Let us suposse that we are building a database in which:

-- a. A row of Foo may be associated with zero-one-or-many rows of Bar.

-- b. A row of Bar can be associated with zero-one-or-many rows of Baz.

-- c. A row of Foo is identified by the values of its own columns
--    (Qux, Corge, Grault, Garply, Etcetera) alone.

-- d. A row of Bar is identified by its BarDateTime value of creation along with
--    the FooId value of the Foo row with which it is associated.

-- e. A row of Baz is identified by its BazNumber value along with
--    the FooId and BarDateTime values of the Bar row with which it is associated.


-- 1. The representation of the ‘top layer’ 
--    of the hypothetical conceptual data hierarchy:
CREATE TABLE Foo ( 
    FooId       INT         NOT NULL, -- Column for surrogates.
    Qux         CHAR(60)    NOT NULL,
    Corge       CHAR(80)    NOT NULL,
    Grault      VARCHAR(90) NOT NULL,
    Garply      CHAR(75)    NOT NULL,
    Etcetera    CHAR(48)    NOT NULL,
    CreatedDate DATE        NOT NULL,
    --
    CONSTRAINT Foo_PK PRIMARY KEY (FooId),
    CONSTRAINT Foo_AK UNIQUE      (Qux, Corge, Grault, Garply, Etcetera) -- ‘Voluminous’ composite ALTERNATE KEY.  
); 

-- 2. Conveying the ‘middle layer’ of the 
--    conceptual data hierarchy:
CREATE TABLE Bar (
    FooId       INT      NOT NULL,
    BarDateTime DATETIME NOT NULL,
    Waldo       CHAR(30) NOT NULL,
    Etcetera    CHAR(62) NOT NULL,
    --
    CONSTRAINT Bar_PK        PRIMARY KEY (FooId, BarDateTime), -- Composite PK.
    CONSTRAINT Bar_to_Foo_FK FOREIGN KEY (FooId) 
    REFERENCES Foo (FooId)  
); 

-- 3. Portraying the ‘bottom layer’ 
--    of the conceptual data hierarchy.
CREATE TABLE Baz (
    FooId       INT      NOT NULL, -- This component of the PK provides ease of ‘navigation’.
    BarDateTime DATETIME NOT NULL, -- This component of the PK also provides ease of ‘navigation’.
    BazNumber   INT      NOT NULL,  
    Fred        CHAR(28) NOT NULL,
    Etcetera    CHAR(57) NOT NULL,
    CreatedDate DATE     NOT NULL,
    --
    CONSTRAINT Baz_PK        PRIMARY KEY (FooId, BarDateTime, BazNumber), -- Meaningful composite PK.
    CONSTRAINT Baz_to_Bar_FK FOREIGN KEY (FooId, BarDateTime)             -- Composite FK.
    REFERENCES Bar (FooId, BarDateTime)        
);

--
Run Code Online (Sandbox Code Playgroud)

...可以将 (a) 列 FROM tableFoo与 (b) 列 FROM table 连接起来,Baz而不必先“通过” (c) table Bar,利用Foo.FooIdBaz.FooId作为唯一必要条件。就此而言,当在某个数据操作操作中可以节省一个或多个“操作”时,就会有更多的平台资源可用于其他并发进程。

本系列文章中,您可以看到一个更“具体”的概念模式示例及其各自的逻辑表示,其中复合 PK 的配置提供了多种优势。

倾向

尽管如此,这些都是趋势,因此,如前所述,您应该始终检查每一个确切的案例(考虑其对整个场景的影响),以确定为代理附加一列是否有益。

数据约束

另一方面,您在下面引用的段落中提到了一个非常相关的细节:

在创建数据库结构时,我倾向于为每组需要唯一的数据创建唯一的复合键。在它们旁边我通常使用主键(通常是 INT AI id),除非复合键确实足以识别记录。

采取这一细节考虑在内,因为一个替代值不携带业务上下文中的含义,因此它是非常重要的并不是唯一地标识真实一个数据元素,那方面是完全有保证的,在任何时候,通过有意义的自然(无论是单列还是多列,PRIMARY 或 ALTERNATE) KEY 值。

除此之外,记住复合 KEY 与 FK 一起工作对于建立声明性限制具有重要价值,以确保相关行符合概念关系/关联之间存在的基数比。由数据库表表示的实体类型。

如您所知,正确约束数据的任务在数据库管理领域具有重大意义,因为它确保所管理的信息与其在现实世界(即适用的业务环境)中的概念一致。以这种方式,拥有一致的数据,所涉及的操作操作会产生可靠的结果,并且数据库的最终用户(和/或一个或多个共享访问它的应用程序)可以将其用作做出明智决策的宝贵工具.

相关场景

在我对题为“

所以你可能会找到那些帮助帖子。

术语

至于术语问题,您可能还会对我在题为“元”的元帖子中的讨论感兴趣


尾注

a系统控制的代理(即由数据库管理系统生成和分配的代理)在 1979 年由关系范式的创建者Edgar Frank Codd 博士撰写的题为“扩展数据库关系模型以捕获更多含义”的论文中得到了评估。在该论文中,规定除其他事项外,绝不能向数据库用户显示系统控制的代理值,尽管在我观察到的大多数数据库中,该规则并未得到遵守(也许它应该由数据库管理部门强制执行)系统本身,自动)。

这个答案是基于这样一个假设:在手头的场景中,系统控制的代理就像正常的业务上下文值一样显示。值得指出的是,系统控制的代理并不是原始关系模型的一部分,如 1970 年发表的题为“大型共享数据库的数据关系模型”的论文,当然也是由 Codd 博士撰写的。