需要帮助优化这个Django聚合查询

时间:2010-06-06 22:14:18

标签: django optimization

我有以下型号

class Plugin(models.Model):
    name = models.CharField(max_length=50)
    # more fields

表示可以从我的网站下载的插件。为了跟踪下载,我有

class Download(models.Model):
    plugin = models.ForiegnKey(Plugin)
    timestamp = models.DateTimeField(auto_now=True)

因此,要构建一个显示按下载排序的插件的视图,我有以下查询:

# pbd is plugins by download - commented here to prevent scrolling
pbd = Plugin.objects.annotate(dl_total=Count('download')).order_by('-dl_total')

哪个有效,但速度很慢。平均只有1000个插件。响应是3.6 - 3.9秒(使用本地PostgreSQL数据库的devserver),其中类似的视图具有更简单的查询(按插件发布日期排序)需要160毫秒左右。

我正在寻找有关如何优化此查询的建议。我真的更喜欢查询返回Plugin个对象(而不是使用values),因为我为其他视图共享相同的模板(按评级插件,按发布日期插件等等)。 ),所以模板期待Plugin个对象 - 而且我不知道如果没有对插件对象的引用我会怎么得到像absolute_url这样的东西。

或者,我的整个方法注定要失败吗?有没有更好的方法来跟踪下载?我最终想为他们上传的插件提供一些不错的下载统计信息 - 比如每天/每周/每月下载。我是否必须在某个时候计算和缓存下载?

编辑:在我的测试数据集中,每个插件有10-20个下载实例 - 在生产中我希望这个数字对于许多插件来说要高得多。

2 个答案:

答案 0 :(得分:0)

注释显然很慢,因为他们需要更新数据库中的每个记录。

一种直接的方法是对db字段进行非规范化。在插件模型上使用download_count字段,该字段在新的下载保存时增加。使用插件上的聚合查询排序。

如果您认为下载更新的插件将会有太多下载,您可以通过cron更新插件上的download_count字段。

答案 1 :(得分:0)

这似乎异常缓慢。但是,在您的查询中没有任何明显的东西会导致这种缓慢。我过去做过非常相似的查询,数据集较大,而且它们在几毫秒内完成。

我现在唯一的建议是安装Django调试工具栏,并在其SQL选项卡中找到有问题的查询并转到EXPLAIN以使数据库在执行时准确地告诉您它正在做什么。例如,如果它正在进行子查询,请检查它们是否正在使用索引 - 如果不是,则可能需要在db中手动定义一个。如果您愿意,请在此处发布EXPLAIN的结果,如果可能的话,我会进一步提供帮助。