2

日付で分割され、次の形式で名前が付けられた一連のテーブルがあります。

public.schedule_20121019

特定の日数の間、これらのテーブルのリストを正常に返すことができます。

SELECT 'public.schedule_' || to_char(current_date - d, 'YYYYMMDD')
FROM generate_series(6, 0, -1) s(d);

select * fromしかし、これらのテーブルのそれぞれを実行し、結果を新しいテーブルに挿入する良い方法は何ですか? ありがとう!

4

3 に答える 3

2

If they are partitioned by date then query the parent table. If you want to create a new table:

create table another_table as
select *
from schedule_parent
where the_date between current_date - 6 and current_date

If you want to insert into an existent table:

insert into another_table
select *
from schedule_parent
where the_date between current_date - 6 and current_date

A partitioned table has a check constraint:

create table schedule_20121012 (
    check (date the_date = date '20012-10-12')
) inherits (schedule_parent);

So when you query for a date from the parent table the planner knows which table to look for:

select * from schedule_parent where date the_date = date '20012-10-12'

I have a set of tables using inheritance. The table usuarios has children partitioned by one of its columns. One of its children:

\d+ usuarios_25567
             Table "public.usuarios_25567"
 Column  |  Type   | Modifiers | Storage | Description 
---------+---------+-----------+---------+-------------
 usuario | integer | not null  | plain   | 
 data    | integer | not null  | plain   | 
 wus     | integer | not null  | plain   | 
 pontos  | real    | not null  | plain   | 
Indexes:
    "ndx_usuarios_25567" UNIQUE, btree (usuario)
Check constraints:
    "b25567" CHECK (data = 25567)
Foreign-key constraints:
    "fk_usuarios_25567" FOREIGN KEY (data) REFERENCES datas(data_serial)
Inherits: usuarios
Has OIDs: no

Its check constraint is the data column. Now look at the query plan when I use that column to filter the query on the parent table:

explain select * from usuarios where data = 25567;
                                          QUERY PLAN                                          
----------------------------------------------------------------------------------------------
 Result  (cost=0.00..26590.45 rows=1484997 width=16)
   ->  Append  (cost=0.00..26590.45 rows=1484997 width=16)
         ->  Seq Scan on usuarios  (cost=0.00..0.00 rows=1 width=16)
               Filter: (data = 25567)
         ->  Seq Scan on usuarios_25567 usuarios  (cost=0.00..26590.45 rows=1484996 width=16)
               Filter: (data = 25567)
(6 rows)

It will only look at that table. Not the other hundreds of tables.

于 2012-10-19T22:57:01.660 に答える
1

パーティショニングについては、詳細なドキュメントを参照してください。豊富な情報があり、それからいくつかあります。テーブル継承を使用してパーティショニングを行います。

2つの注意点:パーティショニングが実際に問題を解決することを確認してください。古いデータを削除したり、日付範囲をクエリしたりするのに適しています。現実的には、個別のパーティションには、機能させるために少なくとも数百万の行が必要です。

もう1つの注意点:現在の状態では、Postgresqlのパーティショニングは数十のテーブルに対して機能します。何百ものストレッチのようです。毎日ではなく、毎月のパーティションを検討してください。

于 2012-10-19T22:24:15.033 に答える
1

私はそれを解決する方法を考え出しました:

CREATE OR REPLACE FUNCTION looper(_schema varchar, _partition varchar,
                                  _traceback integer, _table varchar)
RETURNS VOID AS $$
DECLARE row RECORD;
BEGIN
    FOR row IN
        SELECT table_schema
            , table_name
        FROM
            information_schema.tables
        WHERE
            table_type = 'BASE TABLE'
        AND
            table_schema = _schema
        AND
            table_name IN (
                SELECT _partition || to_char(current_date - d, 'YYYYMMDD')
                FROM
                    generate_series(_traceback, 0, -1) s(d)
            )
        ORDER BY table_name
    LOOP
        EXECUTE 'INSERT INTO ' || _table || ' SELECT schedule_date FROM ' ||
            quote_ident(row.table_schema) || '.' ||
            quote_ident(row.table_name);
    END LOOP;
END;
$$ LANGUAGE plpgsql VOLATILE;
于 2012-10-20T00:06:23.930 に答える