Django在迁移中添加ForeignKey约束后添加RunSQL操作

问题描述 投票:0回答:1

我正在使用Django 2.1Python 3.6MySQL 8

数据库的表很大,有很多大行,因此迁移到该表需要花费数小时才能完成。我发现如果我从该表中删除全文索引,它将启用inplace alghorithm修改表-它的速度更快。

所以我需要在Django中利用它。我考虑过将全文索引删除为第一个迁移操作,并在所有其他操作之后再次创建它。

operations = [
    migrations.CreateModel(
        name='NewModel',
        fields=[
            ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
        ],
        options={
            'abstract': False,
        },
    ),
    migrations.RunSQL(
        ('DROP INDEX fulltext_idx_content ON summarizer_model',),
        ('CREATE FULLTEXT INDEX fulltext_idx_content ON summarizer_model(content)',),
    ),
    migrations.AddField(
        model_name='model',
        name='new_model',
        field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='new_models_objects', to='summarizer.new_model'),
    ),
    migrations.RunSQL(
        ('CREATE FULLTEXT INDEX fulltext_idx_content ON summarizer_model(content)',),
        ('DROP INDEX fulltext_idx_content ON summarizer_model',),
    ),
]

((我在代码窃听器上方迅速将其“匿名化”,因此,如果存在一些逻辑错误,请原谅-这里不是这种情况:))]

问题是,Django迁移总是将添加ForeignKey约束作为最后一个操作。因此,在我的最后一个RunSQL之后创建了索引。这使其操作非常慢(用新列复制整个表)。

是否有克服的方法?我猜想仅将另一个迁移文件用于索引创建会很奇怪。我只想在迁移时临时删除索引。

谢谢

python mysql django django-migrations
1个回答
0
投票

[在深入研究Django迁移的内部之后,我发现Django中的某些迁移操作将SQL添加到架构对象中的deferred_sql列表中。因此,知道解决我的问题的方法是从RunSQL操作继承。我没有立即执行SQL,而是将其附加到deferred_sql列表中,...就是这样!

class DeferredForwardRunSQL(RunSQL):
def database_forwards(self, app_label, schema_editor, from_state, to_state):
    schema_editor.deferred_sql.append(self.sql[0])

我还需要从迁移中修改最后一个RunSQL操作:

operations = [
    migrations.CreateModel(
        name='NewModel',
        fields=[
            ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
        ],
        options={
            'abstract': False,
        },
    ),
    migrations.RunSQL(
        ('DROP INDEX fulltext_idx_content ON summarizer_model',),
        ('CREATE FULLTEXT INDEX fulltext_idx_content ON summarizer_model(content)',),
    ),
    migrations.AddField(
        model_name='model',
        name='new_model',
        field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='new_models_objects', to='summarizer.new_model'),
    ),
    DeferredForwardRunSQL(
        ('CREATE FULLTEXT INDEX fulltext_idx_content ON summarizer_model(content)',),
        ('DROP INDEX fulltext_idx_content ON summarizer_model',),
    ),
]

倒退效果也很好

© www.soinside.com 2019 - 2024. All rights reserved.