【问题标题】:Django add RunSQL operation after adding ForeignKey constraint in migrationDjango在迁移中添加ForeignKey约束后添加RunSQL操作
【发布时间】:2020-08-21 04:32:19
【问题描述】:

我正在使用 Django 2.1Python 3.6MySQL 8

数据库有相当大的表,其中包含大量大行,因此应用于此表的迁移需要数小时才能完成。我发现如果我从这个表中删除 全文索引,它会启用修改表的 inplace 算法 - 它更快。

所以我需要在 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】:

    在深入了解 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',),
        ),
    ]
    

    也适用于向后

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-08
      • 1970-01-01
      • 2018-05-10
      • 2014-05-02
      • 1970-01-01
      • 2020-03-12
      • 2011-06-07
      相关资源
      最近更新 更多