13

Postgresql 9.1 データベースを備えた電子商取引ポータルがあります。1 つの非常に重要なテーブルには、現時点で 3,200 万件のレコードがあります。すべてのアイテムを配信したい場合、このテーブルは 3 億 2000 万のレコード (主に日付) に増加します。これは重いでしょう。

そこで水平分割・シャーディングを考えています。この表の項目を横に 12 個 (1 か月に 1 個) に分割できます。そのための最善の手順とテクニックは何ですか? データベース内の水平分割で十分でしょうか、それともシャーディングについて考え始める必要がありますか?

4

3 に答える 3

24

3 億 2000 万は小さくはありませんが、実際には巨大でもありません。

これは、テーブルで実行するクエリに大きく依存します。クエリに常にパーティション キーを含めると、「通常の」パーティショニングが機能する可能性があります。

この例は、PostgreSQL wiki にあります:
http://wiki.postgresql.org/wiki/Month_based_pa​​rtitioning

このマニュアルでは、パーティショニングの注意点についても説明しています:
http://www.postgresql.org/docs/current/interactive/ddl-partitioning.html

シャーディングについて考えている場合は、Instagram (PostgreSQL を利用) がどのようにシャーディングを実装したかを読むことができます。

http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram

読み取りクエリがほとんどの場合、別のオプションとして、ストリーミング レプリケーションを使用して複数のサーバーをセットアップし、読み取りアクセス用にホット スタンバイに接続し、書き込みアクセス用にマスターに接続して読み取りクエリを分散することもできます。pg-pool IIはそれを (ある程度) 自動的に行うことができると思います。これをパーティショニングと組み合わせて、クエリの実行時間をさらに短縮できます。

あなたが冒険好きで、すぐにそうする必要がない場合は、透過的な水平スケーリングをサポートすることを約束する Postgres-XC を検討することもできます:
http://postgres-xc.sourceforge.net/

まだ最終リリースはありませんが、それほど長くはかからないようです

于 2012-04-21T07:07:54.233 に答える
1

パーティショニングのサンプル コードを次に示します。t_master はアプリケーション t_1 で選択/挿入/更新/削除するビューであり、t_2 は実際にデータを格納する基になるテーブルです。

create or replace view t_master(id, col1)
as 
select id, col1 from t_1
union all
select id, col1 from t_2


CREATE TABLE t_1
(
  id bigint PRIMARY KEY,
  col1 text
);

CREATE TABLE t_2
(
  id bigint PRIMARY KEY,
  col1 text
);



CREATE OR REPLACE FUNCTION t_insert_partition_function()
returns TRIGGER AS $$
begin
raise notice '%s', 'hello';
    execute 'insert into t_'
        || ( mod(NEW.id, 2)+ 1 )
        || ' values ( $1, $2 )' USING NEW.id, NEW.col1 ;
    RETURN NULL;
end;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION t_update_partition_function()
returns TRIGGER AS $$
begin
    raise notice '%s', 'hello';
    execute 'update t_'
        || ( mod(NEW.id, 2)+ 1 )
        || ' set id = $1, col1 = $2 where id = $1' 
        USING NEW.id, NEW.col1 ;
    RETURN NULL;
end;
$$
LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION t_delete_partition_function()
returns TRIGGER AS $$
begin
    raise notice '%s', 'hello';
    execute 'delete from t_'
        || ( mod(OLD.id, 2)+ 1 )
        || ' where id = $1' 
        USING OLD.id;
    RETURN NULL;
end;
$$
LANGUAGE plpgsql;



CREATE TRIGGER t_insert_partition_trigger instead of INSERT
ON t_master FOR each row 
execute procedure t_insert_partition_function();

CREATE TRIGGER t_update_partition_trigger instead of update
ON t_master FOR each row 
execute procedure t_update_partition_function();

CREATE TRIGGER t_delete_partition_trigger instead of delete
ON t_master FOR each row 
execute procedure t_delete_partition_function();
于 2013-10-31T10:27:37.977 に答える