Django 查询性能

Posted

技术标签:

【中文标题】Django 查询性能【英文标题】:Django Query Performance 【发布时间】:2015-12-08 16:15:12 【问题描述】:

我有一个关于 django 查询的与性能相关的问题。

假设我有一个包含 10,000 条记录的员工表。现在,如果我要随机选择 5 名年龄大于或等于 20 岁的员工,假设大约 5,500 名员工年龄在 20 岁或以上。 django 查询将是:

Employee.objects.filter(age__gte=20).order_by('?')[:5]

这个查询在 mysql 中的原始对应物将是:

SELECT * FROM `database`.`employee` 
WHERE `employee`.`age` >= 20
ORDER BY RAND ()
LIMIT 5;

从 django 查询的外观来看,数据库首先返回 5,500 条记录,然后 python 按随机或我们选择的任何顺序对这些记录进行排序,并返回前 5 条记录的一部分,而原始查询将仅返回数据库中的 5 条记录直接。

我的问题是这两个查询之间是否存在性能差异?如果是这样,哪个更好,为什么?

【问题讨论】:

好问题 - 我不知道!不过看看这个答案,你应该能够应用他们建议的步骤来找出答案。 嘿,对不起! This one 【参考方案1】:

我快速检查了我现有的项目:

queryset = BlahModel.objects.order_by('?')[:5]
print queryset.query

结果是:

SELECT `blah_model`.`id`, `blah_model`.`date` FROM `blah_model` ORDER BY RAND() LIMIT 5;

所以,它们是一样的。

我不会对结果太惊讶,因为django ORM是sql查询结果和django对象之间的直接映射,所以order_by('?')会等于ORDER BY RAND(),甚至[:5]语句也被翻译成mysql 中的LIMIT(这里是doc 和doc)。

【讨论】:

【参考方案2】:

您看到的任何性能问题都不是因为 django。正如尚旺已经指出的那样,Django 执行的查询与原始查询完全相同。问题在于 rand() 调用。

正如在其他地方解释的那样,包括一些 StackOveflow 答案,例如:https://***.com/a/6911022/267540 麻烦是由于必须为每一行计算随机值这一事实引起的。幸运的是,您有一个 WHERE 子句可以减少行数。但是随着数据的增长,您的查询将逐渐变得越来越慢。

这个链接有几个关于如何克服这个问题的不同建议http://www.warpconduit.net/2011/03/23/selecting-a-random-record-using-mysql-benchmark-results/

【讨论】:

避免为每一行调用RAND() 是很棘手的。有关问题,请参阅my blog。

以上是关于Django 查询性能的主要内容,如果未能解决你的问题,请参考以下文章

Django-数据库查询性能相关

Django QuerySet 与原始查询性能

使用 annotate Exists 时提高 Django 查询集性能

带有嵌套查询(Django + React)的 Graphql 瓶颈性能使前端应用程序无法使用。请帮忙 :'(

Django查询数据库性能优化

django_orm查询性能优化