4

http://www.postgresql.org/docs/8.1/interactive/ddl-partitioning.htmlのドキュメントごとにパーティション化されたテーブルのセットを設定しました

CREATE TABLE t (year, a);
CREATE TABLE t_1980 ( CHECK (year = 1980) ) INHERITS (t);
CREATE TABLE t_1981 ( CHECK (year = 1981) ) INHERITS (t);
CREATE RULE t_ins_1980 AS ON INSERT TO t WHERE (year = 1980)
    DO INSTEAD INSERT INTO t_1980 VALUES (NEW.year, NEW.a);
CREATE RULE t_ins_1981 AS ON INSERT TO t WHERE (year = 1981)
    DO INSTEAD INSERT INTO t_1981 VALUES (NEW.year, NEW.a);

私の理解では、t(year、a)VALUES(1980、5)に挿入すると、t_1980になり、t(year、a)VALUES(1981、3)にINSERTすると、t_1981になります。 。しかし、私の理解は間違っているようです。まず、ドキュメントから次のことを理解できません

「現在、行をマスターテーブルに挿入してはならないことを指定する簡単な方法はありません。マスターテーブルのCHECK(false)制約はすべての子テーブルに継承されるため、この目的には使用できません。1つの可能性は次のとおりです。常にエラーを発生させるONINSERTトリガーをマスターテーブルに設定します(または、上記のような一連のルールを使用する代わりに、このようなトリガーを使用してデータを適切な子テーブルにリダイレクトすることもできます)。

上記は、CHECK制約とルールを設定しているにもかかわらず、INSERTが正しいテーブルに移動するように、マスターテーブルにトリガーを作成する必要があることを意味しますか?その場合、パーティション化をサポートするデータベースのポイントは何でしょうか?自分で別々のテーブルを設定することはできますか?一連の値をマスターテーブルに挿入しましたが、それらの行は継承されたテーブルではなく、マスターテーブルに残っています。

2番目の質問。行を取得するときに、マスターテーブルから選択する必要がありますか、それとも必要に応じて個々のテーブルから選択する必要がありますか?次はどのように機能しますか?

SELECT year, a FROM t WHERE year IN (1980, 1981);

更新:自分の質問に対する答えを見つけたようです

「COPYコマンドはルールを無視することに注意してください。COPYを使用してデータを挿入する場合は、データを親ではなく正しい子テーブルにコピーする必要があります。COPYはトリガーを起動するため、パーティションを作成する場合は通常どおりに使用できます。トリガーアプローチを使用したテーブル。」

私は実際にCOPYFROMを使用してデータをロードしていたため、ルールは無視されていました。TRIGGERで試してみます。

4

3 に答える 3

4

間違いなくトリガーを試してください。

ルールを実装したいと思う場合は、実行しないでください(頭に浮かぶ唯一の例外は、更新可能なビューです)。詳細については、depeszによるこのすばらしい記事を参照してください。

実際には、Postgresは物事の読み取り側でのパーティショニングのみをサポートしています。パーティションへの挿入方法を自分で設定することになります-ほとんどの場合、トリガーします。ニーズとアプリケーションによっては、パーティションに直接挿入するようにアプリケーションに教える方が速い場合があります。

分割されたテーブルから選択する場合、CHECK制約が適切に設定され(例に含まれている)、constraint_exclusionパラメーターが正しく設定されている限り、マスターテーブルでSELECT ...WHERE...を実行できます。

8.4の場合:

SET constraint_exclusion = partition;

<8.4の場合:

SET constraint_exclusion = on;

そうは言っても、私は実際、Postgresのやり方が本当に好きで、自分で頻繁に使用しています。

于 2010-06-19T14:24:24.717 に答える
1

上記は、CHECK制約とルールを設定しているにもかかわらず、INSERTが正しいテーブルに移動するように、マスターテーブルにトリガーを作成する必要があることを意味しますか?

はい。ポイント5を読む(セクション5.9.2)

その場合、パーティション化をサポートするデータベースのポイントは何でしょうか?自分で別々のテーブルを設定することはできますか?

基本的に、子テーブルのINSERTSは明示的に実行する必要があります(トリガーを作成するか、クエリで正しい子テーブルを指定することによって)。ただし、パーティション化はSELECTSに対して透過的であり、(このスキーマのストレージとインデックス作成の利点を考えると)それがポイントです。(さらに、パーティション化されたテーブルが継承されるため、スキーマは親から継承されるため、一貫性が保たれます)。

于 2010-06-19T17:52:14.657 に答える
1

トリガーはルールよりも間違いなく優れています。今日、マテリアライズド・ビュー・テーブルのパーティション化を試してみましたが、トリガーの解決策で問題が発生しました。なんで ?私はRETURNINGを使用していて、現在のソリューションはNULLを返します:)しかし、これが私のために機能するソリューションです-私が間違っている場合は私を修正してください。1.いくつかのデータが挿入された3つのテーブルがあり、マテリアライズする必要のあるデータを含むビュー(viewfooと呼びます)があります。2.最後のテーブルへの挿入には、INSERT INTO matviewtable SELECT * FROM viewfoo WHERE recno=NEW.recno;を介してマテリアライズドビューテーブルに挿入するトリガーがあります。それはうまく機能し、私はRETURNINGrecnoを使用しています。(recnoはSERIALタイプ-シーケンスです)。

マテリアライズド・ビュー(テーブル)は巨大であるため、パーティション化する必要があります。私のテストによると、この場合のSELECTの方が少なくとも10倍高速です。パーティショニングの問題:*現在のトリガーソリューションRETURN NULL-したがって、RETURNINGrecnoを使用できません。(現在のトリガーソリューション= depeszページで説明されているトリガー)。

解決策:3番目のテーブルのトリガーをマテリアライズドビューテーブルに挿入しないように変更しました(そのテーブルはパーティション化されたテーブルの親です)が、パーティション化されたテーブルを3番目のテーブルから直接挿入する新しいトリガーを作成しました。マテリアライズド・ビュー表は自動的に更新され、RETURNINGrecnoは正常に機能します。これが誰かに役立ったら嬉しいです。

于 2012-02-03T18:32:21.903 に答える