Как интегрировать декларативное разбиение таблиц postgresql 10/11 (т. Е. Предложение PARTITION BY) в модель Django? - PullRequest
0 голосов
/ 02 ноября 2018

В PostgreSQL 10 введено декларативное разбиение таблиц с предложением PARTITION BY, и я хотел бы использовать его для модели Django.

В принципе, все, что мне нужно сделать, это ввести предложение PARTITION BY в конце оператора CREATE TABLE, который создает Django ORM.

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 оператор (по крайней мере, пока).

Последней идеей будет получение оператора CREATE TABLE, который генерирует модель Django, перед отправкой запроса, например, sql = Measurement.get_statement() где Measurement - модель. Затем я могу добавить предложение PARTITION BY и отправить запрос напрямую. Я не мог найти метод, который возвращает заявление. Я прошел через Django create_model код , и sql сгенерирован и напрямую отправлен в базу данных , поэтому было бы нелегко извлечь из него оператор.

Кто-нибудь знает, как этого достичь, чтобы я мог использовать преимущества Django ORM?

1 Ответ

0 голосов
/ 11 января 2019

Подход, который я предлагаю попробовать, заключается в использовании редактора схемы захвата SQL для сбора SQL, необходимого для выполнения create_model. Вот что, кстати, делает sqlmigrate особенность .

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)'.

...