2016-10-21 3 views
1

PostgreSQLデータベースにmilion行を挿入するときにパフォーマンス上の問題が発生します。PostgreSQLへのデータの大量挿入

ミリオンローの配列を持つJSONオブジェクトを送信しています。

各行について、データベーステーブルにレコードを作成します。一度に複数の挿入を試してみましたが、問題は残っています。

これを処理する方法がわかりません。私はCOPYコマンドが最速であることを読んでいます。

パフォーマンスを向上させるにはどうすればよいですか?

ログを配列として持つMy JSONオブジェクト: 配列ログにはミリオンローがあります。

{"type":"monitoring","log":[ 
["2016-10-12T20:33:21","0.00","0.00","0.00","0.00","0.0","24.00","1.83","-0.00","1","1","-100.00"], 
["2016-10-12T20:33:23","0.00","0.00","0.00","0.00","0.0","24.00","1.52","-0.61","1","1","-100.00"]]} 

私の現在のコード(私は一度に複数の行を実行することができるように私は動的ステートメントを構築しています):

IF(NOT b_first_line) THEN 
      s_insert_query_values = right(s_insert_query_values, -1); --remove te leading comma 

      EXECUTE format('INSERT INTO log_rlda 
        (record_node_id, log_line, log_value, timestamp, record_log_id) 
      VALUES %s;', s_insert_query_values); 

      s_insert_query_values = ''; 
      i_num_lines_buffered = 0; 
     END IF; 
     END IF; 

s_insert_query_valuesは含まれています

内部の各値を"log"内の配列は、それ自身の行(列:log_value)に挿入する必要があります。これは、INSERTは(s_insert_query_values参照)のように見える方法です:

INSERT INTO log_rlda 
        (record_node_id, log_line, log_value, timestamp, record_log_id) 
      VALUES 
    (806, 1, 0.00, '2016-10-12 20:33:21', 386), 
    (807, 1, 0.00, '2016-10-12 20:33:21', 386), 
    (808, 1, 0.00, '2016-10-12 20:33:21', 386), 
    (809, 1, 0.00, '2016-10-12 20:33:21', 386), 
    (810, 1, 0.0, '2016-10-12 20:33:21', 386), 
    (811, 1, 24.00, '2016-10-12 20:33:21', 386), 
    (768, 1, 1.83, '2016-10-12 20:33:21', 386), 
    (769, 1, 0.00, '2016-10-12 20:33:21', 386), 
    (728, 1, 1, '2016-10-12 20:33:21', 386), 
    (771, 1, 1, '2016-10-12 20:33:21', 386), 
    (729, 1, -100.00, '2016-10-12 20:33:21', 386), 
    (806, 2, 0.00, '2016-10-12 20:33:23', 386), 
    (807, 2, 0.00, '2016-10-12 20:33:23', 386), 
    (808, 2, 0.00, '2016-10-12 20:33:23', 386), 
    (809, 2, 0.00, '2016-10-12 20:33:23', 386), 
    (810, 2, 0.0, '2016-10-12 20:33:23', 386), 
    (811, 2, 24.00, '2016-10-12 20:33:23', 386), 
    (768, 2, 1.52, '2016-10-12 20:33:23', 386), 
    (769, 2, -0.61, '2016-10-12 20:33:23', 386), 
    (728, 2, 1, '2016-10-12 20:33:23', 386), 
    (771, 2, 1, '2016-10-12 20:33:23', 386), 
    (729, 2, -100.00, '2016-10-12 20:33:23', 386) 

ソリューション(i_node_id_listは、私はこのクエリの前に選択されたIDを含んでいる):

SELECT i_node_id_list[log_value_index] AS record_node_id, 
        e.log_line-1 AS log_line, 
        items.log_value::double precision as log_value, 
        to_timestamp((e.line->>0)::text, 'YYYY-MM-DD HH24:MI:SS') as "timestamp", 
        i_log_id as record_log_id 
       FROM (VALUES (log_data::json)) as data (doc), 
       json_array_elements(doc->'log') with ordinality as e(line, log_line), 
       json_array_elements_text(e.line)  with ordinality as items(log_value, log_value_index) 
       WHERE log_value_index > 1 --dont include timestamp value (shouldnt be written as log_value) 
       AND log_line > 1 

答えて

1

あなたはネスト解除の2つのレベルが必要です。

select e.log_line, items.log_value, e.line -> 0 as timestamp 
from (
    values ('{"type":"monitoring","log":[ 
    ["2016-10-12T20:33:21","0.00","0.00","0.00","0.00","0.0","24.00","1.83","-0.00","1","1","-100.00"], 
    ["2016-10-12T20:33:23","0.00","0.00","0.00","0.00","0.0","24.00","1.52","-0.61","1","1","-100.00"]]}'::json) 
) as data (doc), 
    json_array_elements(doc->'log') with ordinality as e(line, log_line), 
    json_array_elements(e.line) with ordinality as items(log_value, log_value_index) 
where log_value_index > 1; 

json_array_elementsの最初の呼び出しは、()log属性からすべての配列要素を抽出します。 with ordinalityは、その配列内の各行を識別することを可能にします。 2番目の呼び出しは、各要素を行から取得します。with ordinalityは、配列内の位置を見つけることができます。

上記のクエリでは、これを返します。

log_line | log_value | timestamp    
---------+-----------+---------------------- 
     1 | "0.00" | "2016-10-12T20:33:21" 
     1 | "0.00" | "2016-10-12T20:33:21" 
     1 | "0.00" | "2016-10-12T20:33:21" 
     1 | "0.00" | "2016-10-12T20:33:21" 
     1 | "0.0"  | "2016-10-12T20:33:21" 
     1 | "24.00" | "2016-10-12T20:33:21" 
     1 | "1.83" | "2016-10-12T20:33:21" 
     1 | "-0.00" | "2016-10-12T20:33:21" 
     1 | "1"  | "2016-10-12T20:33:21" 
     1 | "1"  | "2016-10-12T20:33:21" 
     1 | "-100.00" | "2016-10-12T20:33:21" 
     2 | "0.00" | "2016-10-12T20:33:23" 
     2 | "0.00" | "2016-10-12T20:33:23" 
     2 | "0.00" | "2016-10-12T20:33:23" 
     2 | "0.00" | "2016-10-12T20:33:23" 
     2 | "0.0"  | "2016-10-12T20:33:23" 
     2 | "24.00" | "2016-10-12T20:33:23" 
     2 | "1.52" | "2016-10-12T20:33:23" 
     2 | "-0.61" | "2016-10-12T20:33:23" 
     2 | "1"  | "2016-10-12T20:33:23" 
     2 | "1"  | "2016-10-12T20:33:23" 
     2 | "-100.00" | "2016-10-12T20:33:23" 

上記のステートメントの結果は、直接それをループせずにデータを挿入するために使用することができます。それは多くの個々の挿入を行うより速くする必要があります。

ただし、正確なrecord_node_idまたはrecord_log_idを上記の結果にどのように組み込むことができないのかはっきりしません。

+0

速い回答ありがとうございました データは異なる方法でアンネストされています。 「行配列」の各値について、最初の値を除いて、行がlog_rldaに挿入されます。 log_rldaの列の説明: record_node_id値の意味を説明するレコードノードを参照します。 は、ログデータ の行番号をlog_line log_value各値 record_log_id「ラインアレイ」の最初の値が、私は「s_insert_query_values」は含まれていたものととして、あなたの最初の質問に返事したデータ のセットを指し タイムスタンプ。 – Vern

+0

@Vern:私の編集 –

+0

を参照して、正しいrecord_node_idを統合する問題を解決してください。私は以前に収集したIDの配列から正しいIDを選択するために次の文を編集しました。 私はlog_value_indexを使って反復処理します。それはかなり良い作品と私​​はこれまでのところ大幅なパフォーマンスの向上を得ている。トピックに解決策を追加しました – Vern

関連する問題