パーティション化するかしないか?


8

SO、外部ブログ投稿、マニュアルに関するいくつかの質問をすでに読んだことがある

それでも、自分のケースを考慮してパーティション分割を行うべきかどうか疑問に思っています。

ケース-簡略化

顧客データの保存。下記の表の名前はすべて、わかりやすくするために作成されています。

  1. 顧客によって識別可能で非物理的な存在であるオブジェクト、およびオンデマンドで顧客にオブジェクトを送り返す必要がある場合にオブジェクトが実際に格納される物理オブジェクト、または他の方法でオブジェクトを処理する。それらは多対多の関係でマッピングされます。objects_nonphysicalobjects_physicalobjects_mapping_table

  2. 2番目の多対多の関係は、これらの非物理オブジェクトとそのメトリックの間です。いくつかのメトリックにバインドされているオブジェクトがあります。metricsmetrics_objects_nonphysical

  3. 非物理オブジェクトと物理オブジェクトの両方に、子と親の関係である階層テーブルがあります。objects_nonphysical_hierarchyobjects_physical_hierarchy

各顧客のニーズと要件に応じて、物理オブジェクトに関するデータを提供することも、ゼロから作成する必要がある場合もあります。基本的に、私がする必要があるのは:

  • 高速のための社内体制の維持INSERTおよびSELECTマッピングが場所を取るために起こっているのはここであるため、ステートメントを。

  • 外部顧客が非物理オブジェクトを表示および操作できるようにシステムを維持します -データの高速検索。ステートメントの効率に対する強いニーズSELECT -このデータは、多くの顧客がいつでも検索できるようになっています。

私の配慮

データにアクセスし、データを表示して操作する顧客がいる可能性がありますが、それは、データを取得したり、データを処理している請負業者である必要はありません。

これにより、システムにテーブルパーティション分割を導入し、どのパーティションデータが該当するか(請負業者のパーティション分割)を常に把握していることを考慮し、次に、顧客のパーティション分割が必要な外部顧客向けのメインテナンスシステムに進みました。(これは、自動化ツールと一連のルールを使用して顧客の方法でデータを書き換えるのを遅らせるため、顧客ごとにテーブルごとに1つのパーティションのみをスキャンします。

データ量

特に新しい顧客のオブジェクトとメトリックをインポートする場合、私のデータは常に増加します。システムに到着する新しいデータのペースは、長期的に見て現時点では予測できません。誰が次の顧客になるかがわからない場合、実際に測定する方法はありません。現在、2つの顧客があり、各テーブルのすべての顧客に対して100万行が多かれ少なかれあります。しかし、将来的には、新規顧客の数が1,000万人になると予測しています行程度になるています。

ご質問

これらの質問はすべて互いに関連しています。

  1. ここでパーティショニングを本当に考慮すべきですか、それとも過剰ですか?私は常に正確に1つをスキャンしているので、それは役に立つと考えていますパーティションを。
  2. パーティショニングがFK最適な方法である場合、自分のニーズを考慮して最も効果的に制約を適用するにはどうすればよいですか?私は行くべきconstraint triggersですか、それとも内部システムのアプリケーション層に保つべきですか、それとも他の方法でしょうか?
  3. パーティショニングがうまくいかない場合、何に飛び込むべきですか?

十分なデータが提供されていない場合は、下のコメントでお知らせください。



3
一般に、インデックスやパーティションなどのオーバーヘッドなしで本番
環境

1
パーティショニングを使用すると、特定の種類のクエリのみが高速化され、他の種類のクエリはヒットします。書き込みもヒットします。パーティショニングは最初に行うべきものではありません。私は、近い将来にプレーンインデックスを使用して問題がなく、それらに到達したときにそれらのブリッジを通過すると思います。500万行はそれほど大きくありません。:これは、速度の比較に有用なブログかもしれないif-not-true-then-false.com/2009/...
dizzystar

2
dizzystarに同意します。今は気にしません。到達したら橋を渡ります。現在Postgresでパーティション分割を行うと、適切な外部キーを使用することが(不可能ではないにしても)困難になります(これは9.7で変更される可能性がありますが、まだ解決されていません)。5,000万行のテーブルであっても、必ずしもパーティション分割の候補とは限りません。行の数を大幅に削減するクエリの等価条件が主にある場合、適切なインデックス付けは長い道のりを手に入れることができます。
a_horse_with_no_name 2016年

1
私にとって、「請負業者のためのパーティション分割」が何を意味するのかは明確ではありません。請負業者が使用するテーブルは、顧客に属するテーブルとは異なりますか?顧客Aが顧客Bのデータにアクセスしなければならないことはありますか?そうでない場合は、顧客固有のデータを顧客ごとのスキーマに分離するのが良い方法かもしれませんが、必ずしもパフォーマンスのためではなく、懸念事項(セキュリティ/プライバシーの向上など)を分離するためです。
dezso 2016年

回答:


1

あなたの質問には多くのオープンエンドがありますが、特に次の場合は、顧客によるパーティション化が適切な方法になる可能性があります。

  • 多くの顧客を期待し、
  • それぞれに大量のデータが含まれる可能性があります(「トン」はRAMキャッシュサイズよりもはるかに大きいことを意味します)。
  • ほとんどのデータセットは相互に排他的です(各顧客には異なるデータのサブセットが表示されます)。

ルールまたはトリガーはパフォーマンスのオーバーヘッドであり、回避できます。

これらの線に沿って何かを考えてください:

BEGIN;

CREATE USER tenant1;
CREATE USER tenant2;

CREATE SCHEMA app;
CREATE SCHEMA tenant1;
CREATE SCHEMA tenant2;

CREATE TABLE app.objects_nonphysical(id int);
CREATE TABLE app.objects_physical(id int);
CREATE TABLE app.objects_mapping(id int);    
CREATE TABLE tenant1.objects_nonphysical() INHERITS(app.objects_nonphysical);
CREATE TABLE tenant1.objects_physical() INHERITS(app.objects_physical);
CREATE TABLE tenant1.objects_mapping() INHERITS(app.objects_mapping);
CREATE TABLE tenant2.objects_nonphysical() INHERITS(app.objects_nonphysical);
CREATE TABLE tenant2.objects_physical() INHERITS(app.objects_physical);
CREATE TABLE tenant2.objects_mapping() INHERITS(app.objects_mapping);

GRANT USAGE ON SCHEMA tenant1 TO tenant1;
GRANT USAGE ON SCHEMA tenant2 TO tenant2;
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA tenant1 TO tenant1;
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA tenant2 TO tenant2;

/* TEST: simulate login as customer */
SET SESSION AUTHORIZATION tenant2;
/* No schema needed - default search_path works */
SELECT count(*) FROM objects_nonphysical; 

ROLLBACK;

それを維持するためのトリガー/ルールは必要ありません。

ここにはオープンエンドがあります-それは単なるドラフトです...いくつかの問題:

  • PK、FK、およびインデックスは「継承」されません。
  • それらを作成しても、マスターテーブルにはPKは適用されません。
  • すべてのテナントに同じシーケンスを使用することでこれを克服できます
  • 明らかに、アプリケーションはこのモデルに合わせて調整する必要があります

0

ここでパーティショニングを実装しても問題はありませんが、システムで実際に新しいパーティションが必要になるまで、単一のパーティションを使用してください。パフォーマンスに関しては、主キーなどを処理するためのオーバーヘッドはごくわずかです。

挿入をリダイレクトするためのルール、および主キーの外部テーブルを使用することをお勧めします(たとえばCREATE TABLE objects_physical_ids (id bigserial NOT NULL PRIMARY KEY)、idsテーブルに行を挿入してNEW.idにコピーする1つの関数トリガー(たとえばINSERT INTO objects_physical_ids DEFAULT VALUES RETURNING id INTO NEW.id;)、および削除を処理する他のトリガー)と更新、および継承された各テーブルに対してこれらの関数トリガーを実行するトリガー(新しい継承されたテーブルを作成するときにこれを行うことを忘れないでください!)そして、すべての関連テーブルはFOREIGN KEY、関連するIDテーブル(のような外部キーアクションを含む)を持つことができます。ON UPDATEまたはON DELETE)。


2
ルールとトリガーには間違いなくオーバーヘッドがあり、簡単に測定できます。さらに、それらは複雑さを追加し、デバッグを(はるかに)困難にします。また、この方法を数回行った後、(確かにすべての詳細を知ることなく)空の親テーブルと1つ以上の子パーティションを保持することをお勧めします。パーティションスキームを変更する場合、これは非常に便利です。
dezso 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.