PostgreSQLから構造化データを取得する

PostgreSQLのストアドプロシージャからunningな階層を持つ複雑な構造を返す方法について困惑し、同時に開発者によってフラットなリレーショナルテーブルにプッシュされたツリー構造を解析するためのアプリケーションで巨大な松葉杖を書かないようにしたことがありますか? 答えがイエスの場合、私は尋ねます...





良い一日!

リレーショナルDBMSへのクエリの結果がテーブルであることは誰もが知っています。 テーブルコンテナは、その厳格な構造を考慮して、表示されるデータにいくつかの制限を課します。 たとえば、結合を含む選択の結果は、元のデータトポロジを隠す非正規化構造であり、アプリケーションがそのような結果を処理することを困難にします。 join'ovの数が増えると、状況は悪化するだけです。

PostgreSQL開発者は、複雑なデータセットをカプセル化できる柔軟なデータ構造を自由に使用できるため、すべてが見た目ほど悪いわけではありません。 配列と構造(レコード、複合型)についてです。

ユニオンを使用した上記の選択の結果は、エレガントで厳密に階層的なビューデザインに変わります。



(

table1_column1 int,

table1_column2 varchar,

table1_column3 numeric,

table2_columns t2_columns[]

)









ここで、t2_columnsはフォームの構造です

(

table2_column1 double precision,

table2_column2 timestamp

)









したがって、ネストレベルを上げることにより、任意の複雑な階層構造を送信できます。

私の場合、アプリケーションはPL / pgSQLで記述され、非常に複雑に編成されたデータを返すストアドプロシージャを提供するインターフェイスとして作成されました。 実際、この記事では、シリアル化されたPostgreSQLデータセットを解析する方法について説明しています。



PostgreSQL文字列(レコードをvarcharにキャストすることで取得されるのと同じ文字列)にシリアル化されたデータの解析をすぐに拒否することが決定されました。

より標準化された解析手段を使用するためにデータの表示を変更するというアイデアは、もうすぐではありませんでしたが、開発されました。

既成のソリューションの検索にしばらく時間を費やし、組み込みのxmlやhstoreタイプなどの候補を破棄したため、あらゆる点でアプリケーションにデータを転送する適切な方法はないという結論に達しました(誤っている可能性があります)。



将来のバイクでは、データ表現としてJSONが選択され(コンパクトさとテキスト性のため)、PostgreSQLのネイティブライブラリ(純粋なC)が実装方法になりました。 結果のツールの内部構造については説明しません。特に、非常にシンプルで誰でも簡単に理解できるためです。 実用的な観点からライブラリを検討してください。 一連の機能がインターフェイスとして提供されます。



使用例:



構造をシリアル化します:

 select to_json( row( 10, 'Some text', 12.5, row( 'text in nested record', array[ 1, 2, 3 ] )::text_and_array, array[ 'array', 'of', 'text' ] ) )
      
      







リクエスト結果:

 {"f1":10,"f2":"Some text","f3":12.5,"f4":{"str":"text in nested record","arr":[1,2,3]},"f5":["array","of","text"]}
      
      







データセットをシリアル化します:

 select json_agg( q.*, 'json_field_name1' ), json_agg_plain( q.*, 'json_field_name2' ) from ... as q;
      
      







リクエスト結果:

 {"json_field_name1":[{ ... },{ ... }, ...]} "json_field_name2":[{ ... },{ ... }, ...]
      
      







後に、JSONの解析と構造フィールドへの入力の逆の操作を実行できる機能でライブラリが拡張されました。



構造と配列を逆シリアル化します。

  select from_json( 'some_record_type', '{"field1":"some text","field2":123,"field3":["this","is","array","of","text"]}' ); select arr_from_json( 'some_type[]', '[{"this is array of"},{"records with one field"}]' );
      
      







クエリ結果:

("some text",123,"{\"this\",\"is\",\"array\",\"of\",\"text\"}")







{("this is array of"),("records with one field")}









説明したシリアライザーは、JSON解析ツールを含むランタイム(C ++およびPHPがあります)と組み合わせて使用​​できます。 ベンチマークは、PostgreSQLのビルトインシリアライザーに匹敵するパフォーマンスを示しています。



ご清聴ありがとうございました。コメントと建設的な批判を歓迎します。



図書館リンク




All Articles