Django 在迁移中添加外键约束后添加运行 SQL 操作
Django add RunSQL operation after adding ForeignKey constraint in migration
我正在使用 Django 2.1、Python 3.6 和 MySQL 8 .
数据库非常庞大 table,其中包含大量大行,因此应用于此 table 的迁移需要数小时才能完成。我发现如果我从这个 table 中删除 fulltext index 它会启用 modyfing table 的 inplace alghorithm - 它更快。
所以我需要在 Django 中利用它。
我考虑过删除 fulltext index 作为第一个迁移操作,并在所有其他操作之后重新创建它。
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',),
),
]
(我很快 'anonymized' 上面的代码片段,所以如果有一些逻辑错误那么请原谅 - 这里不是这种情况:))
问题是 Django 迁移总是把添加 ForeignKey 约束作为最后一个操作。所以在我最后一个创建索引的 RunSQL
之后。这使得操作非常缓慢(用新列复制整个 table)。
有办法克服吗?我猜将另一个迁移文件仅用于创建索引会很奇怪。我只想在迁移时临时删除索引。
谢谢
在深入了解 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])
我还需要修改最后一个 运行SQL 迁移操作:
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',),
),
]
也适用于向后
我正在使用 Django 2.1、Python 3.6 和 MySQL 8 .
数据库非常庞大 table,其中包含大量大行,因此应用于此 table 的迁移需要数小时才能完成。我发现如果我从这个 table 中删除 fulltext index 它会启用 modyfing table 的 inplace alghorithm - 它更快。
所以我需要在 Django 中利用它。 我考虑过删除 fulltext index 作为第一个迁移操作,并在所有其他操作之后重新创建它。
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',),
),
]
(我很快 'anonymized' 上面的代码片段,所以如果有一些逻辑错误那么请原谅 - 这里不是这种情况:))
问题是 Django 迁移总是把添加 ForeignKey 约束作为最后一个操作。所以在我最后一个创建索引的 RunSQL
之后。这使得操作非常缓慢(用新列复制整个 table)。
有办法克服吗?我猜将另一个迁移文件仅用于创建索引会很奇怪。我只想在迁移时临时删除索引。
谢谢
在深入了解 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])
我还需要修改最后一个 运行SQL 迁移操作:
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',),
),
]
也适用于向后