ORACLE表设计:M:N表最佳实践

时间:2011-09-16 17:13:54

标签: sql oracle database-design rdbms

我想听听你对这个基本问题的建议:

想象一下这三个表:

    --DROP TABLE a_to_b;
    --DROP TABLE a;
    --DROP TABLE b;
    CREATE TABLE A
      (
        ID   NUMBER NOT NULL ,
        NAME VARCHAR2(20) NOT NULL ,
        CONSTRAINT A_PK PRIMARY KEY ( ID ) ENABLE
      );
    CREATE TABLE B
      (
        ID   NUMBER NOT NULL ,
        NAME VARCHAR2(20) NOT NULL ,
        CONSTRAINT B_PK PRIMARY KEY ( ID ) ENABLE
      );
    CREATE TABLE A_TO_B
      (
        id         NUMBER NOT NULL,
        a_id       NUMBER NOT NULL,
        b_id       NUMBER NOT NULL,
        somevalue1 VARCHAR2(20) NOT NULL,
        somevalue2 VARCHAR2(20) NOT NULL,
        somevalue3 VARCHAR2(20) NOT NULL
      ) ;

您如何设计表a_to_b?

我会给一些讨论初学者:

  • 合成id-PK列或组合a_id,b_id-PK(删除“id”列)
    • 合成时:还有哪些指数/约束?
    • 合并时:还是b_id索引?甚至是b_id,a_id(不这么认为)?
    • 当自己引用这些条目时也合并了吗?
    • 当这些条目将来可能被引用时,也会合并吗?
  • 堆或索引组织表
    • 总是或只有x“somevalue”-columns?

我知道其中一个设计的决定与表格的使用方式(读/写比率,密度等)密切相关,但也许我们得到一个20/80的解决方案作为未来的蓝图读者。

我期待着你的想法!

Blama

3 个答案:

答案 0 :(得分:6)

我总是让PK成为你的例子中两个FK,a_id和b_id的组合。将合成id字段添加到此表没有任何好处,因为您永远不会根据其id的知识来查找行。

使用复合PK为您提供一个约束,以防止a和b之间的关系的同一实例被插入两次。如果需要允许重复的条目,那么在概念级别上您的数据模型就会出现问题。

您在幕后获得的索引(对于我所知道的每个DBMS)将有助于加速常见联接。 b_id上的额外索引有时很有用,具体取决于您经常进行的连接类型。

正如旁注,我不会对我的所有合成pk列使用名称“id”。我更喜欢a_id,b_id。它使管理元数据变得更容易,即使它有点额外的输入。

答案 1 :(得分:1)

CREATE TABLE A_TO_B
      (
        a_id       NUMBER NOT NULL REFERENCES A (a_id),
        b_id       NUMBER NOT NULL REFERENCES B (b_id),
        PRIMARY KEY (a_id, b_id),
        ...
      ) ;

除了你拥有的任何其他密钥之外,ORM要求(或者,在更有意义的ORM中,希望)一个名为“id”的整数列并不罕见。除此之外,没有必要。像这样的id号会使表更宽(这通常会略微降低I / O性能),并且添加一个严格来说不必要的索引。没有必要识别实体 - 现有密钥就是这样 - 并且它会导致新开发人员陷入不良习惯。 (具体来说,为每个表提供一个名为“id”的整数列,并且相信列是唯一需要的键。)

您可能需要这些索引中的一个或多个。

  • A_ID
  • B_ID
  • {a_id,b_id}
  • {b_id,a_id}

我相信Oracle应该自动索引{a_id,b_id},因为这是主键。 Oracle不会自动索引外键。 Oracle's indexing guidelines在线。

一般来说,您需要仔细考虑是否需要ON UPDATE CASCADEON DELETE CASCADE。在Oracle中,您只需要仔细考虑是否需要ON DELETE CASCADE。 (Oracle不支持ON UPDATE CASCADE。)

答案 2 :(得分:0)

到目前为止,其他评论都很好。

还考虑将begin_dt和end_dt添加到关系中。通过这种方式,您可以随时间管理关于每种关系的大量问题。 (考虑基线问题)