Django / Postgres:LIMIT查询集的性能问题

时间:2012-09-25 04:14:20

标签: django performance limit django-queryset

我遇到了一个奇怪的查询性能问题,我很难理解。

以下是我所拥有的模型结构的简化版本,希望它足以说明问题:

class Note(models.Model):
   ...
   name = models.CharField(max_length=50)
   parentNote = models.ForeignKey('self', null=True)
   form = models.ForeignKey('NoteForm', null=True)
   ...

class Event(Note):
   ...
   startDate = models.DateField()
   ...

class Activity(Event):
   ...

Activity模型是我面临的问题的根源。它具有广泛的继承层次,其中没有一个是抽象的。我不知道这是否有助于解决这个问题。 Activity有大约280000条记录,显然,它的父母至少有那么多,如果不是更多的话。

上面没有描述NoteForm模型 - 只需知道它在Activity模型的层次结构外部并且包含少于100条记录。

我正在使用Django 1.3版。

查询某些父Activity的最新“子”活动时出现问题。查询按parentNote字段过滤,按'startDate'字段排序(降序)并使用Python的索引表示法选择第一个结果(根据我的理解,只是将LIMIT 1添加到生成的SQL中)。请参阅下面的代码。

此查询在未找到结果的情况下意外缓慢运行 - 10秒以上。如果找到结果,它会按预期运行 - 远低于1秒。

进一步调查显示以下内容:

  • 这是造成问题的限制。只是做过滤器而不限于第一个结果,并不慢 - 无论是否找到结果。
  • 订购部分是罪魁祸首。删除顺序可以解决问题。
  • parentNote过滤器部分是罪魁祸首。更改过滤器以使用formname字段可以解决问题。

在代码中:

# Original - SLOW
try:
    latest = Activity.objects.filter(
        parentNote=activity.pk
    ).order_by('-startDate')[0]
except IndexError:
    latest = None

# FAST

# No limit
Activity.objects.filter(
    parentNote=activity.pk
).order_by('-startDate')

# No ordering
try:
    latest = Activity.objects.filter(
        parentNote=activity.pk
    )[0]
except IndexError:
    latest = None

# Different filter
try:
    latest = Activity.objects.filter(
        form=activity.pk
    ).order_by('-startDate')[0]
except IndexError:
    latest = None

# Different filter
try:
    latest = Activity.objects.filter(
        name=activity.pk
    ).order_by('-startDate')[0]
except IndexError:
    latest = None

如果问题出在数据库级别,我看不到它。我在django-debug-toolbar的{​​{1}}中运行了上面的“原始”和“无限制”示例。 “Original”花了16秒,“No Limit”花了59ms。我复制了debugsqlshell打印的两个查询,并在pgAdmin中运行它们。 “原始”花了1375毫秒,“无限制”花了94毫秒。所以它更慢,但不是我看到使用ORM的数量。 debugsqlshell肯定会显示查询分析器采用不同的路径,我完全理解。但我无法直接使用SQL重现16秒查询。

所以,总结一下:

  • 我看到LIMIT查询的运行速度远远低于没有LIMIT的相同查询,但只有在没有找到结果时才会运行。
  • 返回结果的查询运行速度不慢 - 除了过滤器的值之外,它们是相同的。
  • 它似乎是过滤器中包含哪些字段以及是否对订阅集进行排序的函数。
  • 它似乎不是数据库级别的问题,因为直接运行SQL不会运行缓慢。

更新

在尝试评论中提出的建议时,上述例子突然停止了这个问题 - 在我找到任何关于原因的证据之前,更不用说实施修复了。我仍然不知道问题是什么,但现在我没有办法重现它以便进一步调查。

0 个答案:

没有答案
相关问题