Database 我们如何处理快速增长的交集表?

Database 我们如何处理快速增长的交集表?,database,database-design,Database,Database Design,例如,我们有表A和表B,它们具有多对多关系。作为一个交集表,表C存储A.id和B.id以及表示两者之间关系的值。或者作为一个具体的例子,想象一下stackexchange,它有一个用户帐户、一个论坛和一个业力分数。或者,一个学生,一门课程,一个年级。如果表A和表B非常大,那么表C可以而且可能会非常快地变得非常大(事实上,让我们假设它确实如此)。我们如何着手处理这样一个问题?有没有更好的方法来设计表格来避免这种情况?没有魔法。如果一些行是连接的,而另一些行不是连接的,则必须以某种方式表示这些信息,

例如,我们有表A和表B,它们具有多对多关系。作为一个交集表,表C存储A.id和B.id以及表示两者之间关系的值。或者作为一个具体的例子,想象一下stackexchange,它有一个用户帐户、一个论坛和一个业力分数。或者,一个学生,一门课程,一个年级。如果表A和表B非常大,那么表C可以而且可能会非常快地变得非常大(事实上,让我们假设它确实如此)。我们如何着手处理这样一个问题?有没有更好的方法来设计表格来避免这种情况?

没有魔法。如果一些行是连接的,而另一些行不是连接的,则必须以某种方式表示这些信息,“关系”方式是“连接”(也称为“链接”)表。是的,连接表可以变大,但幸运的是数据库能够处理大量数据

使用连接表和逗号分隔列表(或类似列表)有很好的理由,包括:

  • 高效查询(通过索引和集群)
  • 引用完整性的强制执行
设计连接表时,请询问以下问题:

  • 我需要只向一个方向查询还是同时向两个方向查询?1
    • 如果一个方向,只需在两个外键上创建一个复合主键(让我们称它们为PARENT\u ID和CHILD\u ID)。顺序问题:如果您从父项查询到子项,PK应该是:{parent_ID,CHILD_ID}
    • 如果两个方向都,也可以按相反的顺序创建一个复合索引,在本例中为{CHILD_ID,PARENT_ID}
  • “额外”数据小吗?
    • 如果,则根据需要在二级索引中添加表格和额外数据。2
    • I,不要对表进行聚类,也不要在二级索引中包含额外的数据。3
  • 是否有任何其他表由连接表作为父表?
      如果<强>是,考虑是否添加代理键可以使孩子FKS保持苗条。但是要注意,如果添加代理密钥,这可能会消除集群的机会
  • 在许多情况下,这些问题的答案都是:是和否,在这种情况下,您的表将类似于此(下面的Oracle语法):

    考虑事项:

    • 组织索引
      :大多数DBMS称之为集群的Oracle特定语法。其他DBMS有自己的语法,有些(MySQL/InnoDB)意味着集群,用户无法关闭它
    • COMPRESS
      :一些DBMS支持。由于聚集表本质上是一个索引,因此也可以对其应用压缩
    • JUNCTION\u TABLE\u IE1
      EXTRA\u DATA
      :由于额外数据包含在二级索引中,DBMS在从子级到父级的方向上进行查询时,无需触摸表即可获得它。主键充当集群键,因此当从父级查询到子级时,会自然地覆盖额外的数据
    实际上,您只有两个B树(一个是聚集表,另一个是二级索引),根本没有表堆。这转化为良好的查询性能(通过简单的索引范围扫描可以满足父到子和子到父方向)和插入/删除行时相当小的开销

    以下是等效的MS SQL Server语法(SAN索引压缩):

    请注意,除非指定了主键非聚集,否则MS SQL Server会自动对表进行群集


    1换句话说,您是否只需要获得给定“父母”的“子女”,或者您可能也需要获得给定子女的父母

    2覆盖允许仅从索引满足查询,并避免了在通过聚集表中的辅助索引访问数据时需要的昂贵的双重查找


    3这样,额外的数据就不会被重复(这会很昂贵,因为它很大),但是您可以避免双重查找,并用(更便宜的)表堆访问来替换它。但是,请注意,这可能会破坏基于堆的表中范围扫描的性能

    你能发布一个模式和一些示例元组吗?谢谢你,这是一个很好的答案,我感谢为后续阅读提供的链接。
    CREATE TABLE JUNCTION_TABLE (
        PARENT_ID INT,
        CHILD_ID INT,
        EXTRA_DATA VARCHAR2(50),
        PRIMARY KEY (PARENT_ID, CHILD_ID),
        FOREIGN KEY (PARENT_ID) REFERENCES PARENT_TABLE (PARENT_ID),
        FOREIGN KEY (CHILD_ID) REFERENCES CHILD_TABLE (CHILD_ID)
    ) ORGANIZATION INDEX COMPRESS;
    
    CREATE UNIQUE INDEX JUNCTION_TABLE_IE1 ON
        JUNCTION_TABLE (CHILD_ID, PARENT_ID, EXTRA_DATA) COMPRESS;
    
    CREATE TABLE JUNCTION_TABLE (
        PARENT_ID INT,
        CHILD_ID INT,
        EXTRA_DATA VARCHAR(50),
        PRIMARY KEY (PARENT_ID, CHILD_ID),
        FOREIGN KEY (PARENT_ID) REFERENCES PARENT_TABLE (PARENT_ID),
        FOREIGN KEY (CHILD_ID) REFERENCES CHILD_TABLE (CHILD_ID)
    );
    
    CREATE UNIQUE INDEX JUNCTION_TABLE_IE1 ON
        JUNCTION_TABLE (CHILD_ID, PARENT_ID) INCLUDE (EXTRA_DATA);