idを想定 UNIQUEだけでなく -UNIQUE INDEXによって強制されます -しかし、NOT NULL 。 (これはテーブル定義にありません。)
SELECT meta_split.key, meta_split.value, count(*)
FROM voc_cc348779bdc84f8aab483f662a798a6a v
CROSS JOIN LATERAL jsonb_each(v.meta) AS meta_split
GROUP BY meta_split.key, meta_split.value;
短い同等物:
SELECT meta_split.key, meta_split.value, count(*)
FROM voc_cc348779bdc84f8aab483f662a798a6a v, jsonb_each(v.meta) AS meta_split
GROUP BY 1, 2;
LEFT [OUTER] JOIN 次のテストWHERE meta_split.value IS NOT NULLが原因で、ノイズが発生しました INNER JOINを強制します とりあえず。 CROSS JOINの使用 代わりに。
また、jsonb とにかく同じレベルで重複キーを許可しません(同じidを意味します) ポップアップできるのは1回のみです (key, value)ごと )、DISTINCT ただ高価なノイズです。 count(v.id) 同じことをより安くします。そしてcount(*) 同等で安価ですが、idを想定しています NOT NULLです 上部に記載されているように。
count(*) 別の実装があります
count(<value>)よりもわずかに高速です 。 count(v.*)とは微妙に異なります 。何があっても、すべての行をカウントします。他の形式はNULLをカウントしませんが 値。
つまり、idである限り NULLにすることはできません -上部に記載されているように。 id 本当にPRIMARY KEYである必要があります 、とにかく内部的に一意のBツリーインデックスとすべての列で実装されます-id ここに-NOT NULLです 暗黙のうちに。または、少なくともNOT NULL 。 UNIQUE INDEX 代替として完全に適格ではありませんが、それでもNULLを許可します 等しいとは見なされず、複数回許可される値。参照:
それとは別に、すべての行をとにかく読み取る必要があるため、ここではインデックスは役に立ちません。したがって、これが非常に安くなることは決してありません。ただし、62k行 jsonbに膨大な数のキーがない限り、これは決して不自由な行数ではありません。 列。
それをスピードアップするための残りのオプション:
-
デザインを正規化します。 JSONドキュメントのネスト解除は無料ではありません。
-
マテリアライズドビューを維持します。実現可能性とコストは、書き込みパターンに大きく依存します。
ここで、インデックスが再び役割を果たす可能性があります...