我有以下型号
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个下载实例 - 在生产中我希望这个数字对于许多插件来说要高得多。
答案 0 :(得分:0)
注释显然很慢,因为他们需要更新数据库中的每个记录。
一种直接的方法是对db字段进行非规范化。在插件模型上使用download_count
字段,该字段在新的下载保存时增加。使用插件上的聚合查询排序。
如果您认为下载更新的插件将会有太多下载,您可以通过cron更新插件上的download_count
字段。
答案 1 :(得分:0)
这似乎异常缓慢。但是,在您的查询中没有任何明显的东西会导致这种缓慢。我过去做过非常相似的查询,数据集较大,而且它们在几毫秒内完成。
我现在唯一的建议是安装Django调试工具栏,并在其SQL选项卡中找到有问题的查询并转到EXPLAIN以使数据库在执行时准确地告诉您它正在做什么。例如,如果它正在进行子查询,请检查它们是否正在使用索引 - 如果不是,则可能需要在db中手动定义一个。如果您愿意,请在此处发布EXPLAIN的结果,如果可能的话,我会进一步提供帮助。