【问题标题】:Slow page generation in Django with 50+ sql queries per pageDjango 中页面生成缓慢,每页 50 多个 sql 查询
【发布时间】:2013-04-10 21:35:47
【问题描述】:

在我的 Django 应用程序中,我注意到具有大量 sql 查询的页面的加载速度比其他页面慢得多。我不是 web 开发的第一天,主要是我与 Drupal 这样的资源大猪打交道,但即使是每页 150 - 200 个 sql 查询的 Drupal 也会在 0.5 - 0.7 秒内生成页面。

另一方面,Django 在每页的平均查询数或多或少的情况下表现非常糟糕。例如,我的一个页面生成了 60 个这样的查询:

SELECT`gamenode_gamenode`.`id`, `gamenode_gamenode`.`title`, `gamenode_gamenode`.`short_desc`, `gamenode_gamenode`.`full_desc`, `gamenode_gamenode`.`slug`, `gamenode_gamenode`.`type`, `gamenode_gamenode`.`source_gameid`, `gamenode_gamenode`.`created`, `gamenode_gamenode`.`updated`, `gamenode_gamenode`.`status`, `gamenode_gamenode`.`promote`, `gamenode_gamenode`.`sticky`, `gamenode_gamenode`.`hit_count`, `gamenode_gamenode`.`game_rank`, `gamenode_gamenode`.`share_count`, `gamenode_gamenode`.`like_count`, `gamenode_gamenode`.`comment_count` FROM `gamenode_gamenode` WHERE `gamenode_gamenode`.`id` = 1058

并将数据输出为一个简单的字符串,生成一个页面需要 1200 毫秒!我这样做只是为了进行测试以生成许多相当简单的查询。如果我将查询数量减少到 10 - 15 个,页面生成时间将恢复到或多或少可以接受的数字。

那么我有一个问题,为什么页面上有很多sql查询时,Django会这么慢?我使用 Rails、Symfony 和 Drupal 进行了类似的比较,所有这些“资源消耗者”的表现都比 Django 好得多。我是不是做错了什么,或者有一些“秘密”设置可以让 Django 中的事情变得更快,或者,也许 Djangonauts 认为这样的时间是正常的,只是努力编写产生尽可能少的查询的代码?请帮我解决这个问题。

【问题讨论】:

  • 有时会有。我不是在谈论原因。我说的是事实。事实上,当页面上的查询数量多于几个时,它的执行速度会很慢。不是慢,而是慢。这在我的理解中是不正常的,尤其是当其他系统(称为性能较低)表现更好时。缓存在这里不合适。我说的是原始结果。
  • 这个速度测试是否与 debug = true 和在开发服务器上相匹配?
  • 您使用的是什么数据库?你是在生产还是开发?你的服务器设置是什么?您通过 Django ORM 在页面上进行了哪些查询(发布您的代码)?数据库中有什么 - 有很多数据吗?您是否安装了 django-debug-toolbar 之类的工具来准确查看正在创建哪些查询以及每个查询需要多长时间?
  • 请发布您如何测试 Django 的代码。你的视图代码是什么?你的型号是什么?您使用什么数据库处理多少数据?如果没有任何具体的东西,就不可能给出一些有用的见解。

标签: django django-models django-orm


【解决方案1】:

是的,Django 的 ORM 很慢。你有三个选择来处理这个问题:

  1. 投诉吧。

  2. 切换到另一个 Web 应用程序框架。

  3. 努力了解为什么您的应用程序会生成如此多的数据库查询,并学习如何有效地使用 Django 的 ORM 以减少查询次数。

(1) 可能在心理上令人满意,但不会解决您的问题; (2) 在 Stack Overflow 上是题外话(但您可以查看维基百科的 Comparison of web application frameworks)。

我们可以在 (3) 方面为您提供帮助,但前提是您向我们展示更多代码。您引用的查询看起来像是 Django 为调用 get() 而生成的典型查询:

GameNode.objects.get(id = 1058)

你不应该在一个页面上运行超过两个这样的查询:如果你想获得很多 GameNodes,你需要在一个查询中获得它们:

GameNode.objects.filter(<criteria>)

或者,如果 GameNode 对象通过您正在查询的另一个模型上的外键与某个其他对象相关,那么您可以使用 Django 的 select_related() 方法获取所有相关的 GameNode 对象。

几乎总有一种方法可以加快速度 (see this testimonial),但我们需要先了解细节,然后才能说出如何去做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    相关资源
    最近更新 更多