他の人が述べたように、パーティショニングがあなたの答えですが、
私はいくつかに分割しますhash(a)
。a
が整数の場合はa%256
良いでしょう。それがテキストの場合は、次のようなものsubstring(md5(a) for 2)
です。
挿入と選択を高速化します。
削除の場合は、より頻繁に実行しますが、小さくし、パーティション化します。私は毎時間(XX:30に)それらを実行し、次のようにします:
delete from table_name
where date<(current_date - interval '1 year')
and
hash(a)
=
(extract(doy from current_timestamp) * 24
+ extract(hour from current_timestamp))::int % 256;
編集:私はこれをテストしました:
create function hash(a text) returns text as $$ select substring(md5($1) for 1) $$ language sql immutable strict;
CREATE TABLE tablename (id text, mdate date);
CREATE TABLE tablename_partition_0 ( CHECK ( hash(id) = '0' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_1 ( CHECK ( hash(id) = '1' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_2 ( CHECK ( hash(id) = '2' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_3 ( CHECK ( hash(id) = '3' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_4 ( CHECK ( hash(id) = '4' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_5 ( CHECK ( hash(id) = '5' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_6 ( CHECK ( hash(id) = '6' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_7 ( CHECK ( hash(id) = '7' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_8 ( CHECK ( hash(id) = '8' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_9 ( CHECK ( hash(id) = '9' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_a ( CHECK ( hash(id) = 'a' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_b ( CHECK ( hash(id) = 'b' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_c ( CHECK ( hash(id) = 'c' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_d ( CHECK ( hash(id) = 'd' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_e ( CHECK ( hash(id) = 'e' ) ) INHERITS (tablename);
CREATE TABLE tablename_partition_f ( CHECK ( hash(id) = 'f' ) ) INHERITS (tablename);
analyze;
explain select * from tablename where id='bar' and hash(id)=hash('bar');
クエリプラン
-------------------------------------------------- -------------------------------------------
結果 (コスト=0.00..69.20 行=2 幅=36)
-> 追加 (cost=0.00..69.20 rows=2 width=36)
-> tablename の Seq Scan (cost=0.00..34.60 rows=1 width=36)
フィルタ: ((id = 'bar'::text) AND ("substring"(md5(id), 1, 1) = '3'::text))
-> tablename_partition_3 tablename の Seq Scan (cost=0.00..34.60 rows=1 width=36)
フィルタ: ((id = 'bar'::text) AND ("substring"(md5(id), 1, 1) = '3'::text))
(6行)
クエリに追加する必要があります。そうしないとhash(id)=hash('searched_value')
、Postgres がすべてのテーブルを検索します。
編集:テーブルを修正するための自動挿入にルールシステムを使用することもできます:
create rule tablename_rule_0 as
on insert to tablename where hash(NEW.id)='0'
do instead insert into tablename_partition_0 values (NEW.*);
create rule tablename_rule_1 as
on insert to tablename where hash(NEW.id)='1'
do instead insert into tablename_partition_1 values (NEW.*);
-- and so on
insert into tablename (id) values ('a');
select * from tablename_partition_0;
id | mdate
----+-------
a |
(1 row)