5

私はそれをcdrsと呼ぶテーブルを持っています:

CREATE TABLE cdrs (
    i_cdr bigint NOT NULL,
    i_cdrs_connection bigint NOT NULL,
    i_call bigint NOT NULL,
    customer_name character varying(156) NOT NULL,
    client_name_id character varying(256) NOT NULL,
    connection_name character varying(156) NOT NULL,
    vendor_name_id character varying(256) NOT NULL,    
    setup_time timestamp with time zone NOT NULL,
    c_result_id bigint NOT NULL,
    v_result_id bigint NOT NULL
    );

親テーブルへの挿入時にトリガーによる継承を使用してパーティションを作成し、更新を実行しました。この関数は挿入を試み、必要なパーティションがない場合は、インデックスを使用して作成します。各パーティションの i_cdrs_connection に Unique Index を作成し、親にも作成しました。

CREATE UNIQUE INDEX i_cdrs_connection ON cdrs(i_cdrs_connection)

CREATE OR REPLACE FUNCTION cdrs_insert_trigger() RETURNS TRIGGER AS $$
BEGIN
    EXECUTE 'INSERT INTO cdrs_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' SELECT ($1).*'
    USING NEW;
    RETURN NULL;
    EXCEPTION
        WHEN undefined_table THEN
            EXECUTE 'CREATE TABLE IF NOT EXISTS cdrs_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' (CHECK ( setup_time >= '''|| to_char(NEW.setup_time, 'YYYY-MM-DD 00:00') ||''' AND setup_time < '''|| to_char(NEW.setup_time + INTERVAL '1 day', 'YYYY-MM-DD 00:00') ||''' )) INHERITS (cdrs)';
            EXECUTE 'CREATE UNIQUE INDEX i_cdrs_connection_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' ON cdrs_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' (i_cdrs_connection)';
            EXECUTE 'CREATE INDEX i_cdr_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' ON cdrs_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' (i_cdr)';
            EXECUTE 'CREATE INDEX i_call_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' ON cdrs_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' (i_call)';
            EXECUTE 'CREATE INDEX setup_time_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' ON cdrs_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' (setup_time)';

        EXECUTE 'INSERT INTO cdrs_'|| to_char(NEW.setup_time, 'YYYY_MM_DD') ||' SELECT ($1).*'
        USING NEW;
        RETURN NULL;
END
$$
LANGUAGE plpgsql;


CREATE TRIGGER fk_checkTrigger_cdrs
BEFORE INSERT ON cdrs
FOR EACH ROW
EXECUTE PROCEDURE cdrs_insert_trigger();

同じパーティションに重複した i_cdrs_connections を挿入しようとすると、一意のキー違反が表示されますが、エラーなしで追加された同じパーティション行から継承された他のパーティションで同じキーを試すとエラーが発生しません。

要約すると、単一のパーティションに対する一意のインデックスは正常に機能しますが、複数のパーティションを持つテーブルでは値が一意ではありません。

私はシーケンスについて知っていますが、これは別のデータベースからコピーされるため、特定のテーブルにはあま​​り使用されず、重複挿入の可能性を排除する必要があります。

4

2 に答える 2

3

これが PostgreSQL の現在の動作です。一意のインデックスは、テーブル全体ではなくパーティションに対応します。いくつかのオプションがあります:

  1. 可能であれば、テーブルを分割して、キー範囲が何らかの方法で排他的になるようにします。つまり、キーデータで分割します。これは、最も簡単で手間のかからない方法です。ここでは、問題となる非キー データのパーティション分割を行っています。

  2. それが機能しない場合は、結合の反対側にパーティション値を追加できます。この時点で、カスタム fkey トリガーが必要であることに注意してください。

  3. 本当に必要な場合は、すべての ID のトリガー管理マテリアライズド ビューを作成し、その上に一意のインデックスを作成できます。

于 2013-03-22T06:51:21.413 に答える