django - 如何在 Django 模型中集成 postgresql 10/11 声明性表分区(即 PARTITION BY 子句)?

标签 django postgresql database-partitioning

PostgreSQL 10 引入了 declarative table partitioning使用 PARTITION BY 子句,我想将它用于 Django 模型。

原则上,我需要做的就是在 Django ORM 创建的 CREATE TABLE 语句末尾引入 PARTITION BY 子句。

CREATE TABLE measurement (
    city_id         int not null,
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);

是否可以将此子句插入模型中?我认为也许有一种方法可以以某种方式将自定义 SQL 附加到 ORM 生成的查询中,例如使用元:

class Measurement(models.Model):
    ...
    class Meta:
        append = "PARTITION BY RANGE (logdate)"

据我所知,上述情况是不可能的。我也研究了 architect库,但它不使用新的 PARTITION BY 子句。相反,它使用继承和触发器,因此代码没有建议我可以附加子句的任何方式(对于其他数据库,例如 MySQL,它也没有)。

我还通过添加 ALTER TABLE... 操作来自定义迁移,例如:

operations = [
    migrations.RunSQL(
        "ALTER TABLE measurement PARTITION BY RANGE (logdate)",
    ),
] 

不幸的是,PostgreSQL 似乎不支持上述(或类似的)ALTER TABLE statement (至少现在还没有)。

最后一个想法是在发送查询之前检索 Django 模型生成的 CREATE TABLE 语句,例如sql = Measurement.get_statement() 其中 Measurement 是模型。然后,我可以附加 PARTITION BY 子句,并直接发送查询。我找不到任何返回语句的方法。我浏览了 Django create_model code并且sql是generated and directly send to the database , 所以从那里提取语句并不容易。

有没有人知道如何以我仍然可以利用 Django ORM 的好处的方式实现这一点?

最佳答案

我建议尝试的一种方法是使用 SQL 捕获模式编辑器来收集执行 create_model 所需的 SQL。这就是力量the sqlmigrate feature顺便说一下。

from django.db.migrations import CreateModel

class CreatePartitionedModel(CreateModel):
    def __init__(self, name, fields, partition_sql, **kwargs):
        self.partition_sql = partition_sql
        super().__init__(name, fields, **kwargs)

    def database_forwards(self, app_label, schema_editor, from_state, to_state):
        collector = type(schema_editor)(
            schema_editor.connection, collect_sql=True, atomic=False
        )
        with collector:
            super().database_forwards(
                app_label, collector, from_state, to_state
            )
        collected_sql = collector.collected_sql
        schema_editor.deferred_sql.extend(
            collector.deferred_sql
        )

        model = to_state.apps.get_model(app_label, self.name)
        create_table = 'CREATE TABLE %s' % schema_editor.quote_name(
            model._meta.db_table
        )
        for sql in collected_sql:
            if str(sql).startswith(create_table):
                sql = '%s PARTITION BY %s' % (sql.rstrip(';'), self.partition_sql)
            schema_editor.execute(sql)

从那时起,您只需将 makemigrations 自动生成的 CreateModel 替换为 CreatePartitionedModel 操作,并确保指定 partition_sql='RANGE (logdate)'

关于django - 如何在 Django 模型中集成 postgresql 10/11 声明性表分区(即 PARTITION BY 子句)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53110555/

相关文章:

python - 使用 Psycopg2 获取日期时间读取中的小时的 SQL 命令

Postgresql 检查插入输入

postgresql - 如何将外键设置为已排序的 id

mysql - 为表中的所有分区设置公共(public)数据目录

sql - MAX()和MAX()OVER PARTITION BY在Teradata查询中产生错误3504

Django 管理员 : How to call an action on a click of custom button?

django - 为什么 django 在数据库中创建许多 session 对象?

mysql - 表分区和 mysql ndb 集群

sql - 我们如何才能获得所有用户名列表而不是使用 django ORM 的用户对象

django - 将文件从一个模型复制到另一个模型