【问题标题】:using unique constraints to enable simpler joins使用唯一约束来实现更简单的连接
【发布时间】:2019-02-02 08:50:22
【问题描述】:

这是一个概念性问题,因为我正在考虑为一组频繁连接的表设计数据库的两种方法。

这是案例 A:

/*SCHEMA*/
CREATE TABLE SCHEMA (
SCHEMA_ID    INTEGER,
CONSTRAINT sch_pk PRIMARY KEY (SCHEMA_ID)
);

/*OBJECTS*/
CREATE TABLE OBJECT (
OBJECT_ID    INTEGER,
SCHEMA_ID    INTEGER NOT NULL,
CONSTRAINT obj_pk PRIMARY KEY (OBJECT_ID),
CONSTRAINT obj_sch_uniq UNIQUE (OBJECT_ID,SCHEMA_ID),
CONSTRAINT obj_fk FOREIGN KEY (SCHEMA_ID) REFERENCES SCHEMA(SCHEMA_ID)
);

/*COLUMNS*/
CREATE TABLE COL (
COL_ID      INTEGER,
OBJECT_ID   INTEGER,
CONSTRAINT col_pk PRIMARY KEY (COL_ID),
CONSTRAINT col_obj_uniq UNIQUE (COL_ID,OBJECT_ID),
CONSTRAINT col_fk FOREIGN KEY (OBJECT_ID) REFERENCES OBJECT(OBJECT_ID)
);

这是案例 B:

/*SCHEMA*/
CREATE TABLE SCHEMA (
schema_id               INTEGER,
CONSTRAINT schema_pk PRIMARY KEY (schema_ID),
);

/*OBJECTS*/
CREATE TABLE OBJECT (
object_id               INTEGER,
schema_id               INTEGER,
CONSTRAINT object_pk PRIMARY KEY (object_id,schema_id),
CONSTRAINT object_schema_fk FOREIGN KEY (schema_id) REFERENCES SCHEMA (schema_id)
);

/*COLUMNS*/
CREATE TABLE COL (
column_id               INTEGER,
object_id               INTEGER,
schema_id               INTEGER,
CONSTRAINT column_pk PRIMARY KEY (column_id,object_id,schema_id),
CONSTRAINT column_object_fk FOREIGN KEY (object_id,schema_id) REFERENCES OBJECT (object_id,schema_id)
);

将针对这些表集运行的常见查询如下: 案例A

SELECT *
FROM METADATA_CONTROL.COL
INNER JOIN METADATA_CONTROL.OBJECT ON METADATA_CONTROL.COL.OBJECT_ID = METADATA_CONTROL.OBJECT.OBJECT_ID
WHERE OBJECT.SCHEMA_ID = 101;

案例 B

SELECT *
FROM METADATA_CONTROL.COL
WHERE SCHEMA_ID = 101;

可以看出,CASE A 需要连接,CASE B 不需要。我的问题:

-我对这两个表结构执行相同的业务需求是否正确? -如果他们这样做,我如何确定要实施哪个案例?

我对不同关系表结构的性能收益/损失的理解很薄弱。这是在 Oracle 12c 上。

感谢在这种情况下提供的任何指导,以及我可以遵循的一些关于查询性能以及它们与约束和连接的关系的额外资源或规则。

谢谢!

【问题讨论】:

  • 您希望每个表中有多少行?
  • 表“模式”
  • 我希望你的数字除以 100。如果是这样的话,我想你选择A还是B都没关系。有几百万行,呵呵,事情就不同了。我不知道该建议什么,对不起。如果可能,创建示例数据集,填充两种情况,运行查询并检查解释计划的样子。选择一个便宜的。另外,我希望受过教育的人能够提出更好的建议。
  • 感谢您抽出宝贵时间发帖。我很感激。我确实计划执行解释计划并看到这一点,但我在概念上想知道并考虑哪种情况最接近“最佳实践”,因为它与关系数据库建模有关。
  • 没问题;我会关注这个问题,因为我很想知道人们会怎么说。

标签: oracle performance join relational-database


【解决方案1】:

这些不是等效模型。

考虑表 OBJECT 中的以下 2 行:

OBJECT_ID    SCHEMA_ID
1            1
1            2

您可以在案例 B 中插入两行。您不能在案例 A 中插入两行。主键毕竟是唯一的 - 所以 PRIMARY_KEY(OBJECT_ID) 意味着 OBJECT_ID 在 OBJECT 表中是唯一的。

现在,如果您愿意让应用程序强制执行“OBJECT_ID 是唯一的”约束,那么您可以使用 CASE B 来存储满足 CASE A 要求的数据。你可能不应该,但你可以。也就是说你可以在CASE A中放入数据库中的所有东西都可以在CASE B中放入数据库中。反之则不然。

所以主要根据正确性在案例 A 和 B 之间进行选择。

在案例 A - 唯一约束是多余的 - 再次查看 OBJECT 表 OBJECT_ID 已经是唯一的。所以你不需要对你的桌子施加那个约束。

您可能想要的是一个索引,其中前导列是 SCHEMA_ID。这可能只是 SCHEMA_ID 或 SCHEMA_ID 和 OBJECT_ID 上的索引。这为您提供 SCHEMA_ID 的典型查询提供了一个良好的数据库访问路径。 COL 表也是如此 - 为了获得最佳性能,您可能需要一个具有前导列 OBJECT_ID 的索引。

如果案例 B 正确,您可以添加索引以支持您的查询,或者颠倒主键中字段的顺序 - 如果您始终按 SCHEMA_ID 进行过滤,您需要一个第一列是 SCHEMA_ID 的索引.主键总是有一个关联的索引,所以你可以利用它。

基本上根据要求决定什么是正确的,然后针对性能进行优化。

【讨论】:

  • 感谢您的回复。关于您提供的示例,我不太同意您所说的。我的理解是,由于约束“UNIQUE(OBJECT_ID,SCHEMA_ID),您的示例将适用于 CASE A。我知道这有点多余,但在 CASE A 中,PRIMARY KEY(OBJECT_ID)之间存在差异(在我的理解中) ) 与 UNIQUE (OBJECT_ID,SCHEMA_ID)。前者指出 OBJECT_ID 是唯一的,表示一行,不可为空且不可约。而后者表示 OBJECT_ID 和 SCHEMA_ID 的组合必须是唯一的。对吗?
  • 何不试试看。像您所做的那样使用主键和唯一约束构建表,看看当您尝试插入这两行时会发生什么。第一个插入会起作用,第二个会失败,因为你违反了主键约束。
  • 我明白了。我确实创建了一些测试表,你是对的,案例 A 不接受你上面的例子。我会更多地研究索引,因为我不是很熟悉。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-17
  • 2017-01-10
  • 1970-01-01
  • 1970-01-01
  • 2015-05-22
  • 2016-09-20
相关资源
最近更新 更多