【问题标题】:Many-to-Many Relationship - Query Performance with large table sizes多对多关系 - 大表的查询性能
【发布时间】:2012-07-30 22:09:10
【问题描述】:

假设这是我的架构:

class modelA(models.Model):
  b = models.ManyToManyField(through='linkModel')

class modelB(models.Model):
  name = models.CharField()

class linkModel(models.Models):
  a = models.ForeignKey(modelA)
  b = models.ForeignKey(modelB)
  (other link-relevant stuff)

在查找链接到 A 的 B 实例时,我可能会遇到查询性能问题,反之亦然。 100,000 行?百万?

使用单个 ForeignKey 关系而不是 ManyToMany(在某些情况下可能重新排列架构)会提供更好的性能吗?

【问题讨论】:

    标签: database django database-design many-to-many relational-database


    【解决方案1】:

    根据我不熟悉的框架的行为,连接可能会传递到后备数据库服务器以执行。如果是这样,那么你会发现索引效率是 O(log n) 并且阻塞点不是连接而是结果集的大小。

    假设有能力的架构设计和索引,批量数据操作性能总是受工作集大小的限制。

    要获得适用于您的数据库服务器、框架和应用程序逻辑的特定组合的明确答案,您将不得不执行测试,这可能与现代实践完全脱节。

    您不一定需要使用大型复杂应用程序进行测试。您可以将有趣的应用程序代码摘录到测试应用程序中。您需要大量数据。

    如果您希望有人已经测试过您的特定场景,那么您需要详细描述您的配置。您已经提供了示例应用程序逻辑,这是一个好的开始。

    可以干扰的事物数量惊人。例如,在 Microsoft SQL Server 2008 数据库上打开 Auto-shrink 选项会产生巨大的开销,并将 TPM 数字减少大约 3 倍。您必须找到并记录这些内容。

    【讨论】:

      【解决方案2】:

      除了Peter Wone said之外,这里是数据库中应该存在的“理想”联结表结构,以便JOIN的两个“方向”以最佳方式执行:

      • 具有由 2 个 FK 组合而成的复合 PK。
      • 具有与 PK 完全“反向”的备用索引。
      • 两个索引(主索引和备用索引)都经过压缩,以最大限度地减少重复前沿字段的开销。
      • 没有代理键(因此我们不需要第三个索引)。
      • clustered。由于备用索引已经包含所有 PK 字段(只是以相反的顺序),因此通常没有与聚簇表中的备用索引相关的开销。并且由于它是covers JOIN,所以没有双重查找。

      Oracle 的语法如下所示:

      CREATE TABLE LINK_MODEL (
          MODEL_A_ID INT,
          MODEL_B_ID INT,
          PRIMARY KEY (MODEL_A_ID, MODEL_B_ID),
          FOREIGN KEY (MODEL_A_ID) REFERENCES MODEL_A (MODEL_A_ID),
          FOREIGN KEY (MODEL_B_ID) REFERENCES MODEL_B (MODEL_B_ID)
      ) ORGANIZATION INDEX COMPRESS;
      
      CREATE INDEX LINK_MODEL_IE1 ON LINK_MODEL (MODEL_B_ID, MODEL_A_ID) COMPRESS;
      

      这样,查询给定 A 的 B 只需要对索引 LINK_MODEL 进行简单的范围扫描,无需任何表堆访问(根本没有表堆)。查询给定 B 的 As 需要对 LINK_MODEL_IE1 进行简单的范围扫描,也不需要任何表堆访问。

      遗憾的是,并非所有数据库都支持集群和索引压缩,但您应该在 DBMS 和 ORM 允许的范围内尽可能多地实现这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-13
        • 2019-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-05-03
        • 1970-01-01
        相关资源
        最近更新 更多