首页 > 解决方案 > 在一个字段上过滤并在另一个字段上排序时 Django 模型的最佳索引

问题描述

我使用链接到 PostgreSQL 的 Django 2.2,并希望优化我的数据库查询。给定以下简化模型:

class Person(model.Models):
    name = models.CharField()
    age = models.Integerfield()

我必须对此进行以下查询,例如,

Person.objects.filter(age__gt=20, age__lt=30).order_by('name')

在模型 Meta 字段中定义索引以优化查询的最佳方法是什么?这四个选项中哪个最好?

    class Meta
        indexes = [models.Index(fields=['age','name']),
                   models.Index(fields=['name','age']),
                   models.Index(fields=['name']),
                   models.Index(fields=['age'])]

例如,是否可以在查询完成时阻止排序?谢谢你。

标签: djangoindexingsql-order-bydjango-queryset

解决方案


这真的是一个 postgres 问题,就像一个 Django 问题一样,对吧?

我认为在排序字段上创建索引很有可能有助于提高性能。但是有很多注意事项,如果它对您真的很重要,您可能需要针对 Postgres 进行一些测试(即,只需在psql中运行一些查询,看看会发生什么)。一些警告包括:

  • 它可能取决于 Django 为您创建的索引类型
  • 当然,Postgres 在运行查询时并不总是使用索引,但如果你有正确的查询和正确的查询(并且如果表中有足够的数据来证明加载索引是合理的),它应该使用索引
  • Django 如何格式化您的 SELECT可能很重要

我建议您创建模型并指定您需要索引。然后使用 Django 调试工具栏找出真正运行的 SELECT 查询。然后,使用manage.py dbshel​​l(又名 psql)打开一个 dbshel​​l,并使用相同的选择运行 ANALYZE。假设您可以解释输出,您将亲眼看到您的索引是否正在发挥作用。如果您愿意,请将 ANALYZE 输出粘贴到此处。

根据这个Postgres 文档ORDER BY 可以通过 btree 索引来辅助。b-tree 类型的索引是 Django 默认为你创建的。

所以,你为什么不试试这个:

class Meta:
    indexes = [models.Index(fields=['age', 'name'])]

然后在 dbshel​​l 中运行EXPLAIN ANALYZE并查看它是否有效。


推荐阅读