Django在订购时不使用索引

Django在订购时不使用索引,django,postgresql,indexing,django-orm,Django,Postgresql,Indexing,Django Orm,我正在尝试优化Django(1.11版)中的一个查询,该查询用于预取。所以我有一个员工档案模型,它与工资的关系如下: 班级工资(模型): # ... staff=models.ForeignKey('StaffProfile',on_delete=models.CASCADE,null=True) title=models.CharField(u('title'),最大长度=50) 类别员工简介(型号): # ... objects=StaffProfileManager.from_querys

我正在尝试优化Django(1.11版)中的一个查询,该查询用于预取。所以我有一个员工档案模型,它与工资的关系如下:

班级工资(模型):
# ...
staff=models.ForeignKey('StaffProfile',on_delete=models.CASCADE,null=True)
title=models.CharField(u('title'),最大长度=50)
类别员工简介(型号):
# ...
objects=StaffProfileManager.from_queryset(StaffQuerySet)()
StaffQuerySet
有一个专用的方法:

class StaffQuerySet(QuerySet):
定义我的预取(
)->QuerySet:
返回self.prefetch\u相关(
预取(
"工资",,
queryset=sweels.objects.filter(
# ...
).订购(
上(‘标题’)
),
至“预取工资”
),
)
我注意到,当我运行此查询时:
sweers.objects.all().order_by(Upper('title'))
my database(PostgreSQL)显然会对结果进行排序(下面是对生成的SQL执行解释的输出):

生成的查询是:

In [25]: str(Wages.objects.all().order_by(Upper('title')).only('title').query)                                                                                                                                                                
Out[25]: 'SELECT "staff_wages"."uuid", "staff_wages"."title" FROM "staff_wages" ORDER BY UPPER("staff_wages"."title") ASC'

因此,我尝试在
title
字段上设置索引。为了实现这一点,我创建了一个迁移:

class Migration(migrations.Migration):
  dependencies = [
    ('staff', '0020_merge_20201116_0929'),
  ]

  operations = [
    migrations.RunSQL(
      sql='CREATE INDEX "staff_wages_title_upper_idx" ON "staff_wages" (UPPER("title"));',
      reverse_sql='DROP INDEX "staff_wages_title_upper_idx";'
    )
  ]

我已经运行了它,我看到它是在数据库中创建的。然而,当我现在运行查询时,
EXPLAIN
给出了完全相同的输出,而我希望它使用我的索引。我做错了什么?我应该使用不同于b树的索引吗?或者说不可能实现我想要的吗?

即使您创建了一个支持排序的索引,如果PostgreSQL认为排序更便宜,它也可能选择不使用它

要确定PostgreSQL是否因为无法选择索引或认为排序更好而不选择索引,可以暂时不鼓励排序:

SET enable_sort = off;
这不会完全禁用排序,但会带来天文数字的成本损失,因此优化器将在可能的情况下选择不同的计划

然后再次解释查询。如果您的索引仍未使用,则无法使用。如果使用索引,则将估计成本与排序计划的成本进行比较。应该低一点


您可以使用
EXPLAIN(ANALYZE)
实际执行查询,并显示执行时间和估计值。这样,您就可以检查优化器是否做出了正确的选择。如果没有,索引扫描会更快,可能是参数
随机页面\u成本
有效缓存\u大小
未设置为正确描述您的系统。

即使您创建了支持排序的索引,如果PostgreSQL认为排序更便宜,也可能选择不使用它

要确定PostgreSQL是否因为无法选择索引或认为排序更好而不选择索引,可以暂时不鼓励排序:

SET enable_sort = off;
这不会完全禁用排序,但会带来天文数字的成本损失,因此优化器将在可能的情况下选择不同的计划

然后再次解释查询。如果您的索引仍未使用,则无法使用。如果使用索引,则将估计成本与排序计划的成本进行比较。应该低一点


您可以使用
EXPLAIN(ANALYZE)
实际执行查询,并显示执行时间和估计值。这样,您就可以检查优化器是否做出了正确的选择。如果没有,索引扫描会更快,可能是参数
random\u page\u cost
effective\u cache\u size
未设置为正确描述您的系统。

还需要考虑由
.filter(…)
生成的
WHERE
子句。生成的SQL语句是什么,表是如何定义的。@LaurenzAlbe我已经用生成的查询更新了我的问题。
.filter(…)
生成的
WHERE
子句也需要考虑。生成的SQL语句到底是什么,表是如何定义的。@LaurenzAlbe我已经用生成的查询更新了我的问题。嗯,我已经玩了一会儿,发现它从不使用索引。在添加WHERE子句之后(正如在问题下的注释中所指出的那样),当只对WHERE子句中使用的列进行索引时,我得到了最好的性能,而对上方(标题)进行索引会导致性能较差。谢谢你的帮助,这是非常有益的:-)好吧,我已经玩了一会儿,我发现它从来没有使用索引。在添加WHERE子句之后(正如在问题下的注释中所指出的那样),当只对WHERE子句中使用的列进行索引时,我得到了最好的性能,而对上方(标题)进行索引会导致性能较差。谢谢你的帮助,这是非常有益的:-)