2017-12-21 2 views
1

私はバッチでデータを処理し、PostgreSQL(9.6、しかし私はアップグレードすることができます)データベースを埋め込むプロジェクトに取り組んでいます。現在の方法は、プロセスが別々のステップで実行され、各ステップが所有するテーブルにデータを追加することです(同じテーブルに2つのプロセスを書き込む場合は、別の列に書き込むことはほとんどありません)。PostgreSQLデータベースのバッチ処理/分割

データがどのように発生するかは、各ステップでデータがますます細かくなる傾向があります。簡単な例として、データソースを定義する1つのテーブルがあります。非常に少数(数十/数百)ですが、これらのデータソースのそれぞれは、データサンプルのバッチを生成します(バッチとサンプルはメタデータを格納するために別々のテーブルです)。各バッチは、典型的には約50kサンプルを生成する。これらのデータポイントのそれぞれは、ステップバイステップで処理され、各データサンプルは、次のテーブルでより多くのデータポイントを生成します。

これはサンプルテーブルで1.5milの行が得られるまでうまくいきました(これは私たちの観点からは大したデータではありません)。これで、バッチのフィルタリングが遅くなり始めます(取得するサンプルごとに約10ms)。また、バッチのデータを取得するための実行時間が5〜10分かかるため、大きなボトルネックになります(フェッチはmsです)。

これらのクエリに関係するすべての外部キーにbツリーインデックスがあります。

私たちの計算はバッチをターゲットにしているので、私は通常、計算中にバッチ全体を照会する必要はありません(これは、クエリ時間が今のところ非常に苦しい時です)。しかし、データ分析のために、バッチ間でアドホックなクエリを可能にする必要があります。

非常に単純な解決策は、バッチごとに個別のデータベースを生成し、必要に応じて何らかの方法でこれらのデータベースを照会することです。各データベースにバッチが1つだけあれば、明らかに1つのバッチのフィルタリングが瞬時になり、問題は解決されます(今のところ)。しかし、その後、私は数千のデータベースで終わるだろうし、データ分析は苦しいものになるだろう。

PostgreSQLの中には、いくつかのクエリで別々のデータベースがあると思われる方法がありますか?理想的には、新しいバッチを「登録」するときに、それぞれのバッチに対してこれを実行したいと思います。

PostgreSQLの世界の外で、私は私の使用目的のために試すべき別のデータベースがありますか?

編集:DDL /スキーマ

私たちの現在の実装で

sample_representationは、すべての処理結果が依存する表です。バッチは真に(batch.id,representation.id)のタプルによって定義されます。私のように遅いが(50Kサンプルについて約5分まで加える、各サンプルについて10ミリ秒)で試み、上記のクエリ

SELECT sample_representation.id, sample.sample_pos 
FROM sample_representation 
JOIN sample ON sample.id = sample_representation.id_sample 
WHERE sample_representation.id_representation = 'representation-uuid' AND sample.id_batch = 'batch-uuid' 

我々が現在どこか1.5秒sample S、2つのrepresentation S、460個のbatch ES周り有します(そのうち49個は処理され、残りのサンプルはそれに関連付けられていません)。これは、各バッチが平均30kサンプルを持つことを意味します。いくつかは約50k持っています。

スキーマは以下のとおりです。すべてのテーブルに関連付けられたメタデータがありますが、この場合はクエリを実行しません。実際のサンプルデータは、違いがある場合に備えて、ディスクには別々に保存され、データベースには保存されません。

create table batch 
(
    id uuid default uuid_generate_v1mc() not null 
     constraint batch_pk 
      primary key, 
    path text not null 
     constraint unique_batch_path 
      unique, 
    id_data_source uuid 
) 
; 
create table sample 
(
    id uuid default uuid_generate_v1mc() not null 
     constraint sample_pk 
      primary key, 
    sample_pos integer, 
    id_batch uuid 
     constraint batch_fk 
      references batch 
       on update cascade on delete set null 
) 
; 
create index sample_sample_pos_index 
    on sample (sample_pos) 
; 
create index sample_id_batch_sample_pos_index 
    on sample (id_batch, sample_pos) 

; 
create table representation 
(
    id uuid default uuid_generate_v1mc() not null 
     constraint representation_pk 
      primary key, 
    id_data_source uuid 
) 
; 
create table data_source 
(
    id uuid default uuid_generate_v1mc() not null 
     constraint data_source_pk 
      primary key 
) 
; 
alter table batch 
    add constraint data_source_fk 
     foreign key (id_data_source) references data_source 
      on update cascade on delete set null 
; 
alter table representation 
    add constraint data_source_fk 
     foreign key (id_data_source) references data_source 
      on update cascade on delete set null 
; 
create table sample_representation 
(
    id uuid default uuid_generate_v1mc() not null 
     constraint sample_representation_pk 
      primary key, 
    id_sample uuid 
     constraint sample_fk 
      references sample 
       on update cascade on delete set null, 
    id_representation uuid 
     constraint representation_fk 
      references representation 
       on update cascade on delete set null 
) 
; 
create unique index sample_representation_id_sample_id_representation_uindex 
    on sample_representation (id_sample, id_representation) 
; 
create index sample_representation_id_sample_index 
    on sample_representation (id_sample) 
; 
create index sample_representation_id_representation_index 
    on sample_representation (id_representation) 
; 
+0

'... 50kサンプル。これらのデータポイントはそれぞれステップごとに処理されます。つまり、1つのポイントを取得した後、次のポイントを取得し、次のポイントを50K回まで取得します。一度にすべてを一挙に検索してみませんか? – joop

+0

"* PostgreSQLの中には、いくつかのクエリで別のデータベースがあると思われる方法がありますか?" - あなたは[shard](https://en.wikipedia.org/wiki/Shard_(database_architecture) [foreign tables](https://www.postgresql.org/docs/current/static/sql-alterforeigntable.html) –

+0

を使用して、1つのサーバから透過的にアクセスします。@joopこれらの50kレコード(約1 1時間に約5〜10分かかります。 ( 'SELECT tblA.propery_a、tblB.propery_bを使って、tblB.id_tblA = tblA.idのところでtblB.batch_id = 'some-uuid'とtblA.some_fk = 'another-uuid''を使って) –

答えて

0

Rendered Schema

周りいじった後、私は解決策を見つけました。しかし、私はまだ元のクエリは本当に多くの時間を要する理由はないと確信しています:

SELECT sample_representation.id, sample.sample_pos 
FROM sample_representation 
JOIN sample ON sample.id = sample_representation.id_sample 
WHERE sample_representation.id_representation = 'representation-uuid' AND sample.id_batch = 'batch-uuid' 

すべてがインデックス化されますが、テーブルはsample_representation中とsampleで150万行を持つ比較的大きいです。私は何が起こるかは、最初にテーブルが結合されてからWHEREでフィルタリングされることです。しかし、結合の結果として大きなビューを作成する場合でも、それは長くかかりませんか?

いずれの場合でも、2つの「大量の」テーブルを結合する代わりにCTEを使用しようとしました。この考え方は早めにフィルタリングしてから後で参加することでした。

WITH sel_samplerepresentation AS (
    SELECT * 
    FROM sample_representation 
    WHERE id_representation='1437a5da-e4b1-11e7-a254-7fff1955d16a' 
), sel_samples AS (
    SELECT * 
    FROM sample 
    WHERE id_video='75c04b9c-e4b9-11e7-a93f-132baa27ac91' 
) 
SELECT sel_samples.sample_pos, sel_samplerepresentation.id 
FROM sel_samplerepresentation 
JOIN sel_samples ON sel_samples.id = sel_samplerepresentation.id_representation 

このクエリにも時間がかかります。ここに理由は明らかです。 sel_samplesおよびsel_samplerepresentationにはそれぞれ50kレコードがあります。結合は、CTEのインデックスされていない列で行われます。

のCTEのためのインデックスが存在しないので、私はインデックスを追加することができますためのビューがマテリアとして、私はそれらを再定式化:

CREATE MATERIALIZED VIEW sel_samplerepresentation AS (
    SELECT * 
    FROM sample_representation 
    WHERE id_representation='1437a5da-e4b1-11e7-a254-7fff1955d16a' 
); 

CREATE MATERIALIZED VIEW sel_samples AS (
    SELECT * 
    FROM sample 
    WHERE id_video = '75c04b9c-e4b9-11e7-a93f-132baa27ac91' 
); 

CREATE INDEX sel_samplerepresentation_sample_id_index ON sel_samplerepresentation (id_sample); 
CREATE INDEX sel_samples_id_index ON sel_samples (id); 

SELECT sel_samples.sample_pos, sel_samplerepresentation.id 
FROM sel_samplerepresentation 
JOIN sel_samples ON sel_samples.id = sel_samplerepresentation.id_sample; 

DROP MATERIALIZED VIEW sel_samplerepresentation; 
DROP MATERIALIZED VIEW sel_samples; 

をこれが解決策よりもハックの詳細ですが、これらのクエリを実行すると1秒かかります! (8分から)