2017-02-12 15 views
1

私は解析アプリケーション用のデータベースを設計しています。私のデータはCSVファイルから読み込まれます。このファイルには、 'feed'というオブジェクトの一連の二重の値(多分100kを超える値)が含まれています。ダブルの配列のJSON列

私はこれらの2倍の配列をPostgreSQLのJSONカラムに保存し、データを「分割」したいと考えています。ファクタ番号(たとえば:1000)を選択します。これは、各JSONに最大1000の値が含まれることを意味します。あなたはCSVで3000個の値を持っているならば、あなたは3行を持つことになり、結果として、各行は以下のように1000の値のJSONが含まれています:

Table feed 
---------------------------------------- 
| id | data | 
| 1 | { data: [1,2,3,4...1000]} 
| 2 | { data: [1001,1002,...,2000]} 
| 3 | { data: [2001,2002,...,3000]} 

あなたが任意の値を更新したい場合は、私は重複します新しい値を持つ各JSON内の配列とその他は-1になります。

あなたは4500に(インデックス1で)値2002を変更したい場合たとえば、その後、テーブルは次のようになります。

Table feed 
---------------------------------------- 
| id | data | 
| 1 | { data: [1,2,3,4...1000]} 
| 2 | { data: [1001,1002,...,2000]} 
| 3 | { data: [2001,2002,...,3000], new_data: [-1,4500,-1,-1...]} 

そして多分私は、このようなJSONデータを記述するためにいくつかの追加のメタデータ列を追加しますarray_length、is_modifed ....のように処理しやすい。

私はこのデザインでCRUD操作を簡単に行うことができますか?レンダリングとチャートのリアルタイム更新には効果的ですか?読み込み、書き込み、更新...この配列データは非常に頻繁に発生するためです。いずれか私にこれについていくつかのアドバイスを与えることができますか?

ありがとうございます。

+0

私はあなたがそのような考案された計画を思い付くことができたかと思います。ポイントは何ですか?私たちが知らなかった何らかの理由/要件がありますか? – jcaron

+0

ほとんどの場合、配列を使用してチャートをレンダリングし、誰かがチャート内の任意のポイントを編集すると、その値が更新され、クライアントは新しいデータ変更をポーリングしてチャートを更新します。だから私はJSONを読みやすく、レンダリングするのに便利だと思います – Barcelona

答えて

3

あなたが記述したシナリオでJSONデータを使用することは非常に悪い考えです。 JSON is a lightweight data-interchange formatとのいずれかJSON操作のために特に適していないリレーショナルデータストレージモデルなどの特に効率的ではないデータストレージとしてデータ操作フォーマットとPostgreSQLなど

(JSON階層的なデータ構造を有する)または大きな配列を有する。

あなたの考えは効率的ではない理由をいくつかのより具体的な理由:配列に千二重の値を置く

  • は、8,000以上のバイト(jsonbデータ型を想定したのデータ構造生成:ダブルスのための8000のバイトを、構造体自体とその記述子のオーバヘッドがあります;規則的なjsonは、すべての値がすべての値の大きさを正確に記述するために少なくとも8文字を持つため、たぶん大きくなります)。つまり、テーブルはTOASTになり、パフォーマンス上のペナルティが発生します。
  • アレイ内の単一の値を更新するには、(メインテーブルとTOASTテーブル内の)レコード全体が書き換えられ、非常に非効率的である必要があります。

ロジックを実装するためのトリガを使用して、PostgreSQL内の単純なリレーショナル構造を使用するほうがずっと優れています。あなたのチャーティングクライアントがJSON文書を入力として期待している場合、PostgreSQLはそれをオンザフライで生成することができます。例えば:

CREATE TABLE feed (
    "index" integer, 
    value  double precision 
); 

CREATE FUNCTION trf_upd_feed RETURNS trigger AS $$ 
BEGIN 
    -- This DELETE statement throws out unwanted data (the -1 values in your example) 
    -- Usually there will be very few rows (just 1?) that get deleted 
    DELETE FROM feed 
    WHERE ("index" - 1)/1000 = (NEW."index" - 1)/1000; -- integer division! 
    RETURN NEW; 
END; 
$$ LANGUAGE plpgsql; 

CREATE TRIGGER tr_feed_update 
BEFORE UPDATE ON feed 
FOR EACH ROW EXECUTE PROCEDURE trf_upd_feed(); 

あなたはJSONオブジェクトとして値のスライスのデータを取得するために、単純なクエリを実行することができチャート作成のためのデータが必要になります。

SELECT json_build_object('data', arr) AS json_data 
FROM (
    SELECT json_agg(coalesce(feed.value, -1)) AS arr 
    FROM generate_series(1001, 2000) i(x) 
    LEFT JOIN feed ON feed."index" = i.x) sub; 

これは全体的にはるかにありますあなたがTOASTテーブルを必要とせず、何も意味しないデータ(すべて-1の値)を格納しないので、効率的です。あなたの説明から

代替

私はあなたのチャートのクライアントは、値の独自のキャッシュを維持して、データベースに新しいデータのために定期的にポーリングアイデアを得ます。そのような場合は、ロジックを変更する必要があります。更新時に値を変更する(レコードを削除する)のではなく、グラフ作成アプリケーションがデータを読み込むときに行う必要があります。その後、

CREATE FUNCTION chart_data (start_idx integer, end_idx integer) RETURNS json AS $$ 
DECLARE 
    json_data json; 
BEGIN 
    SELECT json_build_object('data', arr) INTO json_data 
    FROM (
     SELECT json_agg(coalesce(feed.value, -1)) AS arr 
     FROM generate_series(start_idx, end_idx) i(x) 
     LEFT JOIN feed ON feed."index" = i.x) sub; 

    -- Data has been read, so now it can be deleted 
    DELETE FROM feed 
    WHERE "index" BETWEEN start_idx AND end_idx; 

    RETURN json_data; 
END; 
$ LANGUAGE plpgsql VOLATILE STRICT; 

を単に `SELECT chart_data(1001、2000)を呼び出す;:そのためにあなたが代わりに更新トリガーの機能を必要とする(ので、あなたはすでにそれを作成している場合は、1つのことを削除します)

+0

あなたの答えをありがとう、実際には私たちはDBAを持っていないし、PostgreSQLとPGがJSONをどれくらいサポートしているかはよく分かりません。アイデアは私のチームの提案の1つに過ぎません。 JSONをストレージに使用する必要がありますか? – Barcelona

+0

PGにはJSON文書を操作する関数がありますが(特にバイナリの 'jsonb'データ型に便利です)、一般的にPGにJSONを格納させてクライアント側で操作させるべきです。 PGは単純なJSON文書(構造が整理されていても階層的には深くない)を検索(および索引付け)できますが、一般に複雑な構造をリレーションモデル(1つ以上の表)に逆アセンブルし、 。 – Patrick

関連する問題