PostgreSQL 11の新機能:JSONB変換





以前の投稿では、 INCLUDEインデックス組み込みのWeb検索について読むことができました。 これらの機能はPostgreSQL 11に登場し、そのリリースは10月に予定されています。 今日は、PL / Python( 3f44e3db )およびPL / Perl( 341e1661 )のJSONB変換について説明し 、今後のリリースの新機能のレビューを続けたいと思います。 両方のパッチは、Anton Bykovによって作成されました。



ご存知かもしれませんが、PostgreSQLでは、 CPL / pgSQL 、PL / Perl、PL / Pythonなど、さまざまな言語でストアドプロシージャを作成できます。 PostgreSQLでは、JSONを保存し、その上にインデックスを作成し、ドキュメントでさまざまな操作を実行することもできます。 ドキュメントを格納するための2つの組み込みタイプがあります。JSONは基本的に通常の文字列で、JSONBはより効率的なバイナリ表現を実装します。



ただし、これらのメカニズムの境界には小さな枠があります。 それを説明する最も簡単な方法は例です:



-- !  `create language`   9.1 create extension plpython3u; CREATE OR REPLACE FUNCTION foo(val jsonb) RETURNS int LANGUAGE plpython3u AS $$ assert(isinstance(val, str)) return len(val) $$; select foo('{"aaa":123, "":456}' :: jsonb);
      
      





その結果、コードはエラーなしで実行され、結果24が返されます。つまり、ストアドプロシージャに転送するとき、JSONBは長さの計算元の文字列にエンコードされました。



楽しい事実! 実際、元の文書の長さは22文字であり、何らかの理由で24文字であることが判明しました。奇妙なことに、ここにバグはありません。 この不一致の原因を調べるために宿題として試してください。



だから、結局のところ、ドキュメントを転送したいのですが、行を転送したくないのです。 言うまでもなく、文字列をデコードして戻すことができます。



 CREATE OR REPLACE FUNCTION bar(val_str jsonb) RETURNS int LANGUAGE plpython3u AS $$ import json val = json.loads(val_str) assert(isinstance(val, dict)) plpy.info(sorted(val.items())) return len(val) $$; select bar('{"aaa": 123, "": 456}' :: jsonb);
      
      





結果:



INFO: [('aaa', 123), ('', 456)]

bar

-----

2

(1 row)









本当のようです。 しかし、あなたがそれについて考えるなら、私たちはここで多くの役に立たない仕事をしています-最初にドキュメントをエンコードし、それからすぐにデコードします。 ドキュメントが大きく、ストアドプロシージャが頻繁に呼び出される場合、このエンコード/デコードのオーバーヘッドは非常に大きくなる可能性があります。



問題は、JSONBをPythonまたはPerlに理解できるオブジェクト(配列、辞書/ハッシュなど)の形で渡すだけでよいのでしょうか? できることが判明し、これらのパッチはまさにそれを行います。 大まかに使用する方法は次のとおりです。



 create extension jsonb_plpython3u; CREATE OR REPLACE FUNCTION baz(val jsonb) RETURNS int LANGUAGE plpython3u TRANSFORM FOR TYPE jsonb AS $$ assert isinstance(val, dict) plpy.info(sorted(val.items())) return len(val) $$;
      
      





ところで、反対方向、つまり返されたドキュメントをエンコードするには、次のこともできます。



 CREATE OR REPLACE FUNCTION qux(val int) RETURNS jsonb LANGUAGE plpython3u TRANSFORM FOR TYPE jsonb AS $$ obj = { "val": val } return obj $$;
      
      





PerlとPython 2の場合、すべてが同じ方法で行われるため、対応するコードは提供しません。 さらに、さまざまな境界の場合のコードの複雑さについては説明しません。たとえば、返されたドキュメントで複素数、NaN、±Infが見つかった場合はどうなるか、それだけです。 興味のある読者の皆様、私はあなたがパッチコードに精通することをお勧めします。 それらは、そのような境界ケースをチェックするだけで、テストで十分に覆われています。



このような興味深い機能。 もちろん、それが役立つ状況は頻繁には発生しません。 ただし、JSONB変換の存在を知っていても、問題はありません。



All Articles