7

我的 Django 应用程序有问题。对模型Scope的查询非常慢,经过一些调试后,我仍然不知道问题出在哪里。

当我像查询数据库一样scope = Scope.objects.get(pk='Esoterik I')需要 5 到 10 秒时。数据库的条目少于 10 个,并且主键上有一个索引,所以它太慢了。在数据库上执行等效查询时,SELECT * FROM scope WHERE title='Esoterik I';一切正常,只需要大约 50 毫秒。

如果我查询一组结果scope_list = Scope.objects.filter(members=some_user),然后调用 print(scope_list) 或遍历列表元素,则会发生同样的问题。查询本身只需要几毫秒,但元素的打印或迭代再次需要 5 到 10 秒,但集合只有两个条目。

数据库后端是 Postgresql。同样的问题出现在本地开发服务器和apache上。

这里是模型的代码:

class Scope(models.Model):
    title = models.CharField(primary_key=True, max_length=30)

    ## the semester the scope is linked with
    assoc_semester  =   models.ForeignKey(Semester, null=True) 

    ## the grade of the scope. can be Null if the scope is not a class
    assoc_grade     =   models.ForeignKey(Grade, null=True)

    ## the timetable of the scope. can be null if the scope is not direct associated with a class
    assoc_timetable =   models.ForeignKey(Timetable, null=True)

    ## the associated subject of the scope
    assoc_subject   =   models.ForeignKey(Subject)

    ## the calendar of the scope
    assoc_calendar  =   models.ForeignKey(Calendar)

    ## the usergroup of the scope
    assoc_usergroup =   models.ForeignKey(Group)

    members = models.ManyToManyField(User)

    unread_count = None

更新

这是python分析器的输出。似乎 query.py 被调用了 160 万次——有点太多了。 python分析器输出

4

2 回答 2

3

您应该尝试首先隔离问题。运行 manage.py shell 并运行以下命令:

scope = Scope.objects.get(pk='Esoterik I')
print scope

现在 django 查询只有在非常需要时才会执行。也就是说,如果您在第一行之后遇到缓慢,则问题出在创建查询的某个地方,这表明对象管理器存在问题。下一步是尝试通过 django 执行原始 SQL,并确保问题确实出在管理器上,而不是一般 django 中的错误。

如果您在使用第二行时遇到缓慢问题,则问题要么与查询的实际执行有关,要么与数据的显示\打印有关。您可以在不打印的情况下强制执行查询(查看文档)以找出它是哪一个。

据我了解,但我认为解决此问题的最佳方法是将过程分解为不同的部分,并找出导致缓慢的部分

于 2013-07-31T12:59:48.210 回答
2

为了确定数据库执行时间,最好测试 Django 生成的查询,因为 Django 生成的查询可能不是一个简单的SELECT * from blah blah

要查看 Django 生成的查询:

_somedata = Scope.objects.filter(pk='Esoterik I') # you must use filter in here
print somedata.query.__format__('')

这将显示 Django 生成的完整查询。然后复制它并打开一个 Postgresql 控制台并使用 Postgresql 分析工具:

EXPLAIN ANALYZE <your django query here>;

喜欢:

EXPLAIN ANALYZE SELECT * FROMsomeapp_scope WHERE id = 'Esoterik I';

EXPLAIN将显示平均执行数据,同时ANAYLZE还会向您显示有关该分析执行时间的一些额外数据。

您还可以在这些分析结果中查看 postgresql 在查询执行期间是否使用了任何索引。

于 2013-07-31T13:17:05.003 回答