1

假设这是我的架构:

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(在某些情况下可能重新排列架构)会提供更好的性能吗?

4

2 回答 2

4

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

假设有能力的模式设计和索引,批量数据操作性能总是由工作集的大小决定的。

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

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

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

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

于 2012-08-02T00:06:41.500 回答
2

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

  • 具有由 2 个 FK 组合而成的复合 PK。
  • 具有与 PK 完全“反向”的备用索引。
  • 两个索引(主索引和备用索引)都被压缩,以最小化重复前沿字段的开销。
  • 没有代理键(所以我们不需要第三个索引)。
  • 集群的。由于备用索引已经包含所有 PK 字段(只是以相反的顺序),因此通常没有与聚簇表中的备用索引相关的开销。并且由于它涵盖了 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 允许您这样做。

于 2012-08-02T08:47:06.080 回答