【问题标题】:Django Effecient way to Perform Query on M2MDjango 在 M2M 上执行查询的高效方法
【发布时间】:2020-04-22 21:29:32
【问题描述】:
class A(models.Model)
  results = models.TextField()
class B(models.Model)
  name = models.CharField(max_length=20)
  res = models.ManyToManyField(A)
  • 假设我们有以上 2 个模型。 A 模型拥有数百万个对象。

我想知道获取特定B 对象的所有results objects 的最有效/最快的方法是什么。

  • 假设我们必须检索对象编号为5B 的所有结果
Option 1 :  A.objects.filter(b__id=5)

   (OR)

Option 2 : B.objects.get(id=5).res.all()
  • 选项 1:我的问题是在 A 模型对象上按 id 过滤会花费很多时间吗?因为有数百万个 A 模型对象。
  • 选项 2:问题:B 模型上的 res 字段是否存储了 A 模型对象的 id 值?

我假设选项2 的原因会是一种更快的方法,因为它存储A 模型对象的引用并首先直接获取这些对象值并进行第二个查询以获取结果。而在第一个选项中,按 id 或任何其他字段过滤会占用大量时间

【问题讨论】:

  • 第一个只会查询一次,而后者会查询两次。

标签: django django-models django-rest-framework django-forms django-templates


【解决方案1】:

第一个表达式将产生一个数据库查询。事实上,它会查询:

SELECT a.*
FROM a
INNER JOIN a_b ON a_b.a_id = a.id
WHERE a_b.b_id = 5

第二个表达式将产生两个查询。实际上,首先 Django 将使用如下查询查询以获取特定的 B 对象:

SELECT b.*
FROM b
WHERE b.id = 5

然后它将进行完全相同的查询来检索相关的A 对象。

但是这里没有必要检索A 对象(除非您当然需要它在其他地方)。因此,您进行了无用的数据库查询。

我的问题是按模型对象上的 id 过滤会花费很多时间吗?因为有数百万个 A 模型对象。

数据库通常在外键字段上存储索引。因此,这意味着它将有效过滤。 A 对象的总数通常不相关(因为它使用数据结构来加速搜索,如 B-tree [wiki])。 wiki 页面有一个部分 named An index speeds the search 解释了这是如何工作的。

【讨论】:

  • 感谢您的精彩解释,我想知道默认情况下数据库会在所有字段上存储索引还是只存储 idpk
  • @ArbazzHussain:通常主键确实有索引。您可以通过设置db_index=Truedocs.djangoproject.com/en/dev/ref/models/fields/#db-index 在其他字段上添加额外的索引
猜你喜欢
  • 1970-01-01
  • 2011-09-19
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多