2

テーブルにデータを解析、検証、挿入する最速の方法を探しています( Postgresql 9.3)

データは、1..N 個のアイテムを含む json-array です。

[{"name":"a","value":"1"},{"name":"b","value":"2"}]

テーブルは次のようになります。

CREATE TABLE logs
(
  id serial NOT NULL,
  name text ,
  value text,
  CONSTRAINT "log_Pkey" PRIMARY KEY (id)
);

そのために私はストアドプロシージャを持っています:

CREATE OR REPLACE FUNCTION insert_logs(v json)
  RETURNS  integer AS
$BODY$
DECLARE
    sql text;
    i json;
    logs_part_id int;
BEGIN
    SELECT INTO logs_part_id id from another_table_with_that_id where some_condition.

    sql = '';
     FOR i IN SELECT * FROM json_array_elements(v)
      LOOP
      sql = sql||'insert into logs_'||logs_part_id ||'
        (name, value)
         values( ' ||quote_literal(i->>'name')||' , ' ||quote_literal(i->>'value')||' );';

      END LOOP;
    raise notice '%',sql;

    EXECUTE sql;
    return 1;

END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

(関数は応答ステータスとして整数を返します)

関数呼び出し:

select * from insert_logs('[{"name":"a","value":"1"},{"name":"b","value":"2"}]'::json);

実際には、"insert.." ステートメントはかなり大きく、15 列を挿入する必要があり、明らかに SQL インジェクションを防ぐためにそれらのいくつかをチェックする必要があります。

質問: パフォーマンスを向上させるために、このストアド プロシージャを書き直す方法はありますか? 準備済みステートメントを使用する必要がありますか?

編集。

テーブルのパーティション分割のためにテーブル名が不明であるため、SQL文字列を作成する理由。テーブル名の形式は次のとおりです。logs_ id id - 挿入直前に取得される int。

4

2 に答える 2

2

なぜあなたはSQLマルチステートメント文字列を構築し、EXECUTEそれをまったくingしているのでしょうか?

ただ:

  insert into logs (name, value)
  values( i->>name , i->>value );

PL/PgSQL によってバインドされたパラメーターとして挿入される値であるi->>nameため、明示的な引用符は必要ありません。SQL として解析されることはありません。textinsert

ステートメントを動的に構築する必要がある場合(例: コメントごとにテーブル名を変える)、次のように使用EXECUTE ... USINGformatます。

  EXECUTE format('insert into %I (name, value) values( $1, $2 );', 'logs_'||log_partition_id) 
     USING i->>name , i->>value;

あなたの場合

于 2014-09-22T08:36:10.777 に答える