8

日付によるテーブル パーティション (特にログ) が広く使用されていると想像できますが、問題に対する適切な答えを見つけることができません。

週ごとにテーブル パーティションを作成したい (レコード数が多すぎて月ごとに作成できない)。毎週行う理由は、プロセスの一部として日付を検索するアルゴリズムのデータが必要だからです。

私の問題は、週を考慮してパーティションを作成し、「典型的な」アプローチを使用して手動で作成する必要があることです。このようなもの。

    CREATE TABLE measurement_y2013w01 (
CHECK ( logdate >= DATE '2013-01-07' AND logdate < DATE '2013-01-14' ) 
    ) INHERITS (measurement);

    CREATE TABLE measurement_y2006w02 (
CHECK ( logdate >= DATE '2013-01-14' AND logdate < DATE '2013-01-21' ) 
    ) INHERITS (measurement);

... 

しかし、私はそれが自動的に行われることを望んでいます。毎週1つずつパーティションを作成したくありません。

名前を付けるための私のルールは、パーティションの名前付けの場合は yYYYYwWW にするか、datadYYYYMMDD を開始します。

次のようなものを使用して挿入するときにパーティションをチェックすることを考えました:

 SELECT
    nmsp_parent.nspname AS parent_schema,
    parent.relname      AS parent,
    nmsp_child.nspname  AS child,
    child.relname       AS child_schema
FROM pg_inherits
    JOIN pg_class parent        ON pg_inherits.inhparent = parent.oid
    JOIN pg_class child         ON pg_inherits.inhrelid   = child.oid
    JOIN pg_namespace nmsp_parent   ON nmsp_parent.oid  = parent.relnamespace
    JOIN pg_namespace nmsp_child    ON nmsp_child.oid   = child.relnamespace

パーティションが存在しない場合は、挿入前に作成しますが、挿入されるレコードの数を考慮すると、これは非常に非効率的です。

私の他の選択肢は、このパーティションを作成する外部プロセスを毎週実行することですが、私はこれを避けようとしていました.

たとえば、毎月のチェックに使用される、私が見逃しているこれに対するより効率的なソリューションはありますか?

4

3 に答える 3

5

それでは、それを処理する関数を作成しましょう。

CREATE OR REPLACE FUNCTION create_partition_measurement( DATE, DATE )
returns void AS $$
DECLARE
create_query text;
BEGIN
    FOR create_query IN SELECT

        'CREATE TABLE measurement_' || TO_CHAR( d, 'YYYY_WW' ) || ' (
        CHECK ( EXTRACT(YEAR FROM logdate) = EXTRACT(YEAR FROM TIMESTAMP ''' || d || ''') AND EXTRACT(WEEK FROM logdate) = EXTRACT(WEEK FROM TIMESTAMP ''' || d || ''') )
        ) INHERITS (measurement);'

        FROM generate_series( $1, $2, '1 week' ) AS d LOOP

        EXECUTE create_query;

    END LOOP;
END;
$$
language plpgsql;

これで、次のようなものを呼び出すことができます

SELECT create_partition_measurement ('2015/02/08','2015/03/01'); 

パーティションを作成します。自動化への第一歩、完了。

次のテストテーブルを使用して、自分のデータベースでこれらすべてをテストしました。

CREATE TABLE measurement (id INT NOT NULL PRIMARY KEY, id_user INT NOT NULL, logdate TIMESTAMP NOT NULL);

上記の関数を使用してパーティションを作成した後、次のことができました。

  • 正しいパーティションにデータを挿入します。
  • ある週のデータを別の週のパーティションに挿入しようとすると、エラーが発生します。
  • 数週間分のパーティションを自動作成して・・・
  • パーティションが既に存在する週にパーティションを作成しようとすると、エラーが発生します。

これで十分です=)

次に、作成プロセスの自動化について。私は単純な cron スクリプトを使用して毎月この関数を呼び出し、いくつかの監視スクリプトを使用して、すべてが正常に機能していることを確認しています。cron は次のようになります。

0 0 1 * * /var/lib/postgresql/create_partitions.sh

そして、スクリプトは現在の日付と現在の日付 + 1 か月を使用してコマンドを実行します。次のようになります。

startDate=`date "+%Y/%m/%d"`
endDate=`date -u -d "+1 month -$(date +%d) days" "+%Y/%m/%d"
psql -U "$dbUser" -w -c "SELECT create_partition_measurement('$startDate','$endDate');"

テーブルにインデックス、PK、FK を含める必要がある場合、またはこれらすべてを機能させるためのトリガーを支援する必要がある場合は、お知らせください。

于 2015-01-23T22:14:13.530 に答える