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ドキュメントのネスト解除は無料ではありません。
-
マテリアライズドビューを維持します。実現可能性とコストは、書き込みパターンに大きく依存します。
ここで、インデックスが再び役割を果たす可能性があります...