Python Django—;提高“startswith”性能

Python Django—;提高“startswith”性能,python,sql,django,postgresql,django-orm,Python,Sql,Django,Postgresql,Django Orm,如何提高以下查询的性能 class Worker(models.Model): name = models.CharField(max_length=32, db_index=True) # This line is slow: Worker.objects.filter(name__startswith='John') 我已经在模型中添加了索引,但是。。。它根本没有被使用。然而,当我不使用startswith进行普通筛选时,索引确实起作用: # This line is fast:

如何提高以下查询的性能

class Worker(models.Model):
    name = models.CharField(max_length=32, db_index=True)

# This line is slow:
Worker.objects.filter(name__startswith='John')
我已经在模型中添加了索引,但是。。。它根本没有被使用。然而,当我不使用
startswith
进行普通筛选时,索引确实起作用:

# This line is fast:
Worker.objects.filter(name='John')

为什么索引不与
startswith
一起使用

问题是
startswith
表达式转换为包含
LIKE
运算符的SQL查询,该运算符不利用默认索引

解决方案:添加一个附加索引,其中包含一个特殊的:

逐步:

  • 首先,创建一个空迁移:

    python3 manage.py makemigrations appName --empty
    
  • 添加自定义RunSQL命令:

    class Migration(migrations.Migration):
    
        dependencies = [
            ('stats', '0002_auto_2010213_0159.py'),
        ]
    
        operations = [
            migrations.RunSQL(
                sql=r'''CREATE INDEX "appname_model_field_like_idx" 
                        ON "appname_model" ("fieldname" varchar_pattern_ops);''',
                reverse_sql=r'DROP INDEX "appname_model_field_like_idx";'
            ),
        ]
    

  • 如果您的后端是MySQL,请尝试使用不区分大小写的
    istartswith
    来使用索引:


    Worker.objects.filter(name\u istartswith='John')

    反向sql的附加样式点。Django似乎已经自动添加了这个索引(可能只有在引用的字段上已经有索引的情况下——我不确定)了。
    class Migration(migrations.Migration):
    
        dependencies = [
            ('stats', '0002_auto_2010213_0159.py'),
        ]
    
        operations = [
            migrations.RunSQL(
                sql=r'''CREATE INDEX "appname_model_field_like_idx" 
                        ON "appname_model" ("fieldname" varchar_pattern_ops);''',
                reverse_sql=r'DROP INDEX "appname_model_field_like_idx";'
            ),
        ]