これは、Django + PostgreSQLを使用する場合に、月ごとに比較的迅速かつ簡単にテーブルのパーティション化(パーティション化)を設定する方法に関するトピックです。 上記の多くは、他のフレームワークおよびORMに適しています。
パーティション化とは何か、なぜ必要なのかについては、たとえばhere 、 here 、 hereを読むことができます 。
したがって、Djangoにはプロジェクトがあり、モデルの1つのテーブルは非常に大きくなければなりません。 このテーブルからの読み取りが頻繁に発生し、レコードが作成された期間が常にわかっている場合、パーティション化によりデータベースが高速化されます。
パーティション分割を有効にするクエリを実際に作成したくない場合は、毎回自動化してみましょう。 さて、出力がSQLにあまり詳しくない人でも使用できるものである場合。 私はドキュメントを読みましたので、あなたはする必要はありません。
最初に、ベストプラクティスをすばやく試す方法を説明し、次に内部の問題について説明します。 私たちは次のように行動します:
- パーティション分割コマンドを追加できるように、
syncdb
をキャッチします。 - 確立されたインデックスを引き出し、セクションを作成し、それらのインデックスをアクティブにし、関数とトリガーを追加するSQLを接続します。
- 最終アプリケーションおよびモデルでパーティション化をアクティブにします。
まず、 リポジトリからパッケージをインストールします
pip install git+https://github.com/podshumok/django-post-syncdb-hooks
いくつかのアプリケーションを接続します。
INSTALLED APPS = ( # ... 'post_syncdb_hooks', 'post_syncdb_hooks.partitioning', 'your.app', # ... )
yourapp/models.py
モデルがあります:
from django.db import models class MyModel(models.Model): date_created = models.DateTimeField() my_data = models.IntegerField(db_index=True)
ファイル
yourapp/sql/post_syncdb-hook.postgresql_psycopg2.sql
追加します(必要に応じて間隔を編集できます)。
SELECT month_partition_creation( date_trunc('MONTH', NOW())::date, date_trunc('MONTH', NOW() + INTERVAL '1 year' )::date, 'yourapp_mymodel', 'date_created');
syncdb
実行し
syncdb
。
...およびセクションが作成されます。./manage.py syncdb
これが最初の
syncdb
である場合、作成されたセクションにはインデックスがありません。 これを修正するには、
syncdb
再度実行する必要があります。
さて、ベースの準備はできましたが、Djangoはまだありません。 実際、バージョン1.3以降、DjangoはPostgreSQLの
INSERT INTO
クエリを作成し、
RETURNING...
を追加して
id
挿入されたレコードの
id
を取得します。 また、使用しているパーティション分割方法はこの機能をサポートしていません。
大まかにDjangoで
RETURNING
使用しないように強制できます。
from django.db import connections, DEFAULT_DB_ALIAS connections[DEFAULT_DB_ALIAS].features.can_return_id_from_insert = False
そして、
RETURNING
それだけで使用されないようにモデルを編集できます:
from post_syncdb_hooks.partitioning import to_partition class MyModel(models.Model): "..." #... @to_partition def save(self, *args, **kwargs): return super(MyModel, self).save(*args, **kwargs)
それで、ベースは準備ができています、Djangoは準備ができていますが、準備はできていますか? 読み取り要求によってすべてのセクションのデータベースポーリングが行われないように、パーティショニングが実装されているフィールド(この例では
date_created
)で
date_created
フィルタリングする必要があります。
qs = MyModel.objects.filter(date_created__lte=..., date_created__gt=...)
また、特別な必要なしに、すべてのエントリがどこにも発生しない
count()
ことはありません。たとえば、管理
paginator
がこれを行うことを好みます。
これで全員の準備が整いました。 それだけです
post_syncdb_hooks
に関するpost_syncdb_hooks
post_syncdb_hooks
は、
post_syncdb
シグナルのレシーバーを接続する
post_syncdb_hooks
が含まれています。 このレシーバーまたはフックは、インストールされているすべてのアプリケーションに対して呼び出されます。
sql
フォルダーがこのアプリケーションまたはそのアプリケーションの
models.py
ファイルの隣にあるかどうかを確認し、隣にある場合は、
post_syncdb-hook.sql
または
post_syncdb-hook.(backend).sql
を起動できません。
post_syncdb_hooks.partitioning
には、このようなSQLファイルのみが含まれています。 その中で、開始日、終了日、テーブル名、フィールド名の4つのパラメーターを取るSQL関数を作成します。 関数が呼び出されると、選択されたテーブルのセクションが選択されたフィールドに作成され、開始日から終了日まで月単位で作成されます。また、
INSERT INTO
とセクションテーブルのインデックスのトリガーも作成されます(メインテーブルにインデックスが指定されている場合)。
インデックスに関するフード
私にとって最も退屈で難しいのは、セクションのインデックスを作成することでした。 テーブルを作成するためのSQLが記述されており、パーティションスキームに移行する場合、問題はありません。コピーアンドペーストです。 しかし、Djangoがテーブルを作成するとき、マスターテーブルのインデックスを作成せず、対応するSQLを保存する方法はあまり明確ではありません。 最終的に、私は決定しました:Djangoにインデックスを作成させ(それらはまだ空のままです)、セクションにコピーします。
これを行う方法を決定することは残っています。
psql
には
-E
オプションがあり、内部コマンドによって生成されたSQLを出力します。 だから
sudo -u postgres psql -E db
db=# \di ********* QUERY ********** SELECT n.nspname as "Schema", c.relname as "Name", CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as "Type", pg_catalog.pg_get_userbyid(c.relowner) as "Owner", c2.relname as "Table" FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid WHERE c.relkind IN ('i','') AND n.nspname <> 'pg_catalog' AND n.nspname <> 'information_schema' AND n.nspname !~ '^pg_toast' AND pg_catalog.pg_table_is_visible(c.oid) ORDER BY 1,2; ************************** db=#
少しコピーアンドペーストし 、テーブルテーブルのインデックスを作成するためのすべてがあります。
よろしくお願いします!
ここで紹介するパッケージは、私がいくつかのプロジェクトで使用しており、割り当てられたタスクをうまく処理しています。
これを読んでくれたみんなに感謝します。 何かが誰かに役立つことを願っています。
また、コメントとgithubで見つかった欠点に注意して 、改善と拡張を提案してください。