こんにちは、読者の皆様。
今日の記事では、Djangoアプリケーションを使用してPostgreSQLの階層データモデルを比較することに焦点を当てます。 この記事では、軍隊に近い環境でのパフォーマンスに関心があるため、データベースでは特に純粋な実装を使用していません。
すべてのテストは私のデータに対して行われ、結果はその特定のデータに関連しています。あなたのデータでは、記事で得られた結果と異なる場合があります。
データベースに階層構造を実装するためのモデル
次のモデルを使用して、PostgreSQLでこのような構造を操作できます。
- 隣接モデル(AM) -親が列に格納されている場合のモデル。
- ネストされたセット(NS) -すべてのネストされた要素の範囲が1組の列に格納されているモデル。
- マテリアライズドパスモデル(MP) -要素へのフルパスが列に格納されている場合のモデル。
リレーショナルデータベースでの階層構造の実装の詳細については、 こちらをご覧ください 。
Djangoでの実装には、次のツールが選択されています。
- AM-ForeignKeyに基づくネイティブDjango再帰。
- NS- django-mpttモジュール。
- MP- LtreeFieldラッパーを備えたltree PostgreSQLモジュール。
テスト方法
テストは、15万社のデータセットで実行されます。 時間が測定されます
次のクエリ:
- 木全体を読む
- 任意のノードを読み取ります
- ノードを挿入
- レベル間でサブツリーを移動する
クエリの実行時間は、ランダムに選択されたツリー要素に対する各アイテムの1000リクエストの平均実行時間と見なされます。
テストベッドハードウェア
- CPUコアi5 2.5 GHz
- RAM 1600 MHz DDR3
- SSD Samsung 850 EVO 500GB
テストベンチソフトウェア
- Python 2.7
- Postgres 9.6
- ジャンゴ1.8
- psycopg2
テストツールの説明
テストのために、 別のDjangoアプリケーションが作成されました。 上記のストレージスキームごとに1つずつ、3つのモデルを作成しました。 これは、異なるデータセットで同様のテストをいつでも実行できるようにするために行われます。
このアプリケーションは2つのコマンドを実装します。
-
load_tree
テスト用のデータをロードします - 分析-所定の数のリクエストに基づいてデータを収集および分析します
アプリケーションを実行して統計を収集するには、一連のコマンドを実行する必要があります。
python manage.py migrate python manage.py load_tree < > python manage.py load_tree analize <- >
analize
の結果は、 レポートフォルダーに保存されます。
結果
これらのコマンドを実行した後、私のデータについて、次の結果を受け取りました。 モデルの名前が誤解しないように、テストのモデルとストレージモデルの対応を以下に示します。
- 生 -隣接モデル
- Mptt-ネストされたセット
- Ltree-マテリアライズドパス
木全体を読む
図からわかるように 、 MpttモデルとLtreeモデルはほぼ同じ結果を示しましたが、ネイティブのRawモデルの方が高速であることがわかりました。
任意のノードを読み取ります
このテストでは、前の段落とは異なり、 Mpttモデルは標準実装の速度に追いつきましたが、 Ltreeは逆に結果を悪化させました。 Rawモデルは再帰クエリ(WITH RECURSION)を使用して子孫を取得しますが、それにもかかわらず、最速で動作したことに注意してください。
ノードを挿入
ノードを挿入すると、 Ltreeモデルは再び遅れますが、この場合、ツリーが格納されているパスフィールドがIDレコードで構成されていたことが原因である可能性が最も高いため、それに応じて影響を受ける2つのリクエスト(挿入してからパスフィールドを更新)を行う必要がありましたパフォーマンスについて。
レベル間でサブツリーを移動する
サブツリーを含むノードを移動すると、 Mpttが最悪の結果を示しました。これは、移動するときにポータブルノードのすべてのフィールドを再計算する必要があるためである可能性があります。 Rawの移動は、実際には1つのフィールドを更新するだけなので、最速です。 Ltreeは 、ポータブルサブツリーのすべてのノードのパスを更新する必要があるため、リーダーの背後にはあまりありません。
まとめ
階層構造の実装を比較した後 、 MP (Ltree)モデルの実装が最良の結果を示すことを期待しましたが、驚いたことに、 AM (Raw)モデルのネイティブ実装に負けて2番目の結果しか示しませんでした。 NS (Mptt)モデルの実装は3位になりました。4回のうち2回のテストで、競合他社から大きく外れて負けました。
結果を含む要約表:
モデル | insert_node | move_node | read_node | read_tree |
---|---|---|---|---|
Ltree | 0.001955 | 0.010375 | 0.008745 | 0.025522 |
Mptt | 0.001006 | 0.855293 | 0.00104 | 0.115597 |
生 | 0.001002 | 0.001 | 0.001012 | 0.021957 |
また、他のデータセットでは結果が異なる場合があるため、決定を行う前に、データに対して同様のテストを実施することをお勧めします。
中古品:
- PostgreSQLでのツリーの表現
- SQLのツリー:ネストされたセットと具体化されたパス
- データベース内のツリーのストレージ。
- Djangoのベンチマークツリー構造
- 階層データ構造とDoctrine
- Ltree
- Django-mptt
- Ltreefiled
PSこれは私のブログのオリジナル記事のクロスポストです。
PSソートを追加した後のツリー読み取りチャートを更新