【问题标题】:Django migrations: create a partial index and set `db_index=True` without creating a full index?Django迁移:创建部分索引并设置`db_index = True`而不创建完整索引?
【发布时间】:2017-05-25 09:45:22
【问题描述】:

我正在向一个大表添加一个 NULL 列,并且我想确保它在模型定义中设置了 db_index=True

class MyLargeModel(Model):
    new_field = IntegerField(null=True, default=None, db_index=True)

但对于实际索引,我想使用部分索引:

migrations.RunSQL("""
    CREATE INDEX my_index
    ON mylargemodel (new_field)
    WHERE new_field IS NOT NULL
""")

但是,默认情况下,这意味着 Django 的迁移将创建一个索引(这将非常慢),然后我需要手动删除该索引并创建我自己的。

如何创建一个迁移来告诉 Django Migrations db_index=True 已设置,而无需在数据库中创建索引?

【问题讨论】:

  • 创建自己的索引时为什么要设置db_index=True
  • 我想保留db_index=True,以便未来的开发人员(以及未来的我)知道它已编入索引,而无需四处寻找去想知道发生了什么。我知道我可以添加评论……但我宁愿拥有显式属性。
  • 您可能会发现 class based indexes 功能在即将推出的 Django 1.11 中很有用。

标签: django django-migrations


【解决方案1】:
  1. new_field 添加到MyLargeModel 不带db_index=True 并保存
  2. 运行 makemigrations 以生成将添加 new_field 而没有索引的迁移。
  3. MyLargeModel 定义中更新new_field 并添加回db_index=True
  4. 运行makemigrations 生成标准迁移以将索引添加到MyLargeModel.new_field
  5. 通过将以下自定义类添加到文件顶部来更新从 (4) 的迁移:

    from django.db import migrations, models
    
    class NoopAlterField(migrations.AlterField):
        def database_forwards(self, app_label, schema_editor, from_state, to_state):
            pass
    
  6. 通过将调用从 migration.AlterField 更改为我们的自定义 NoopAlterField 来更新从 (4) 的迁移

    operations = [
        NoopAlterField(
            model_name='mylargemodel',
            name='new_field',
            field=models.IntegerField(...),
        ),
    ]
    

你可以猜到,它所做的只是创建一个NoopAlterField 迁移处理程序,它将更新内部模式跟踪器,但 放弃创建索引的实际数据库步骤。

【讨论】:

    猜你喜欢
    • 2019-12-30
    • 2019-05-26
    • 1970-01-01
    • 1970-01-01
    • 2022-11-24
    • 2017-10-03
    • 2013-01-25
    • 2014-12-12
    • 2014-02-07
    相关资源
    最近更新 更多