4

postgresql で jsonb データ型のパフォーマンスをテストしています。各ドキュメントには、階層化されていない約 1500 個のキーがあります。ドキュメントがフラット化されます。テーブルとドキュメントは次のようになります。

create table ztable0
(
   id serial primary key,
   data jsonb
)

サンプル文書は次のとおりです。

{ "0": 301, "90": 23, "61": 4001, "11": 929} ...

ご覧のとおり、ドキュメントには階層が含まれておらず、すべての値が整数です。ただし、一部は将来テキストになります。

  • 行: 86,000
  • 列: 2
  • ドキュメント内のキー: 1500+

キーの特定の値を検索したり、パフォーマンスによってグループを実行したりすると、パフォーマンスが著しく低下します。このクエリ:

select (data ->> '1')::integer, count(*) from ztable0
group by (data ->> '1')::integer
limit 100

完了するまでに約 2 秒かかりました。jsonb ドキュメントのパフォーマンスを向上させる方法はありますか。

4

1 に答える 1

5

これは の既知の問題です9.4beta2。このブログ投稿をご覧ください。詳細とメール スレッドへのポインタが含まれています。

問題について。

PostgreSQL はTOASTを使用してデータ値を保存します。これは、大きな値 (通常は 2kB 以上) が別の特別な種類のテーブルに保存されることを意味します。また、PostgreSQL は、そのpglz方法を使用してデータを圧縮しようとします (長年使用されてきました)。「試行」とは、データの圧縮を決定する前に、最初の 1k バイトがプローブされることを意味します。そして、結果が満足のいくものでない場合、つまり、プローブされたデータに圧縮が何の利益ももたらさない場合、圧縮しないという決定が下されます。

そのため、初期の JSONB 形式では、値の先頭にオフセットのテーブルが格納されていました。また、JSON のルート キーの数が多い値の場合、最初の 1kB (およびそれ以上) がオフセットで占められていました。これは一連の異なるデータでした。つまり、等しい 2 つの隣接する 4 バイト シーケンスを見つけることができませんでした。したがって、圧縮はありません。

オフセット テーブルを通過する場合、残りの値は完全に圧縮可能であることに注意してください。したがって、オプションの 1 つは、pglz圧縮が適用可能かどうか、およびそれをプローブする場所 (特に新しく導入されたデータ型の場合) をコードに明示的に伝えることですが、既存のインフラストラクチャはこれをサポートしていません。

修正

そのため、JSONB 値内にデータを格納する方法を変更して、pglz圧縮に適したものにすることが決定されました。これは、新しい JSONB オンディスク フォーマットを実装する変更を含む、Tom Lane によるコミット メッセージです。また、形式が変更されたにもかかわらず、ランダム要素のルックアップは依然として O(1) です。

それでも直るまで1ヶ月ほどかかりました。ご覧のとおり、9.4beta3既にタグ付けされているため、公式発表後すぐに再テストできます。

重要な注意:に切り替えるには、ツールを実行pg_dump/pg_restore実行または利用する必要があります。これは、データの保存方法に必要な変更を特定した問題の修正であるため、 とのバイナリ互換性はありません。pg_upgrade9.4beta3beta3beta2

于 2014-10-08T15:11:14.467 に答える