Django使用Annotate而不是Distinct()

时间:2011-08-26 17:09:06

标签: mysql django model annotate

我已经读过distinct()API调用有时会遇到一些性能问题。我想尝试通过orm重写一个查询,避免使用distinct(至少描述差异)。

我的理解是values()执行Group By引擎盖。但是,当我测试这两种方法时,对象的数量会有所不同,具体取决于我是使用distinct()还是使用values()/ annotate()。

   zip_codes = Location.objects.values('zip_code').annotate(zip_count=Count('zip_code')).exclude(zip_code=None).count()

VS

  zip_codes = Location.objects.values_list('zip_code', flat=True).exclude(zip_code=None).distinct()

对这里有什么问题的想法?

谢谢!

1 个答案:

答案 0 :(得分:2)

我只是快速检查了我对具有类似查询的数据库的查询。计数相同,所以我不确定您的数据会导致问题。

尽管如此,我还是对这个前提持怀疑态度。 DISTINCT确实是一个cpu密集型查询。但是,COUNT(*)也是如此,您的第二个查询将首先使用group by运行计数聚合,然后对结果运行COUNT。我会把钱放在单个DISTINCT调用上更快(我还要检查你用来查看的数据库后端)。所有这些与django的ORM几乎没什么关系,而且与你的数据库后端有很多关系。

还要想一想。与基于注释的查询相比,基于不同的查询比其完成的内容更清楚一个数量级。你是否有证据支持DISTINCT在你的情况下会变慢,或者更好的是它现在正在形成一个瓶颈?如果不是,你已经进入了过早优化的范围,并且应该重新考虑你的道路。

Premature Optimization

  

优化仅在重要时才有意义。重要的是,这很重要,但在你知道这很重要之前,不要浪费很多时间去做。即使你知道这很重要,你也需要知道它的重要性。如果没有性能数据,您将不知道要优化什么,并且您可能会优化错误的东西。

     

结果将是模糊的,难以编写,难以调试,并且难以维护无法解决问题的代码。因此,它具有以下双重缺点:(a)增加软件开发和软件维护成本,以及(b)根本没有性能影响。

换句话说,清楚地编写软件,然后在发现问题时将其跟踪到源并进行修复。你之前做的任何事情都会适得其反。花点时间担心哪些索引对您的数据库有影响,以及在哪里使用select_related。这些比你在这里担心的效率高10000%(除非你一直在计算邮政编码,在这种情况下让我向你介绍缓存)