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 查询性能的主要内容,如果未能解决你的问题,请参考以下文章
使用 annotate Exists 时提高 Django 查询集性能