多对多关系 - 使用大表大小查询性能

时间:2012-08-01 23:22:11

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

假设这是我的架构:

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实例时,我可以在什么时候遇到查询性能问题,反之亦然。 10万行?百万?

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

2 个答案:

答案 0 :(得分:4)

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

假设有能力的架构设计和索引,批量数据操作性能始终按工作集的大小进行门控。

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

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

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

令人惊讶的事情可能会干扰。例如,在Microsoft SQL Server 2008数据库上启用“自动缩小”选项会产生巨大的开销,并将TPM数字减少大约3倍。您必须查找并记录这些内容。

答案 1 :(得分:2)

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

  • 复合PK是2个FK的组合。
  • 有一个与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的Bs只需要对LINK_MODEL的索引进行简单的范围扫描,而不需要任何表堆访问(根本没有表堆)。查询给定的B将需要LINK_MODEL_IE1上的简单范围扫描,也不需要任何表堆访问。

不幸的是,并非所有数据库都支持群集和索引压缩,但您应该像DBMS一样实现这一点,而ORM允许您这样做。