PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Otimizando GROUP BY + COUNT DISTINCT na coluna jsonb não aninhada


Assumindo id não apenas UNIQUE - conforme imposto pelo seu UNIQUE INDEX - mas também NOT NULL . (Isso está faltando na sua definição de tabela.)
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;

Equivalente mais curto:
SELECT meta_split.key, meta_split.value, count(*)
FROM   voc_cc348779bdc84f8aab483f662a798a6a v, jsonb_each(v.meta) AS meta_split
GROUP  BY 1, 2;

O LEFT [OUTER] JOIN era ruído porque o seguinte teste WHERE meta_split.value IS NOT NULL força um INNER JOIN de qualquer forma. Usando CROSS JOIN em vez de.

Além disso, como jsonb não permite chaves duplicadas no mesmo nível (o que significa o mesmo id só pode aparecer uma vez por (key, value) ), DISTINCT é apenas ruído caro. count(v.id) faz o mesmo mais barato. E count(*) é equivalente e mais barato, ainda - assumindo id é NOT NULL como indicado no topo.

count(*) tem uma implementação separada e é um pouco mais rápido que count(<value>) . É sutilmente diferente de count(v.*) . Ele conta todas as linhas, não importa o quê. Enquanto o outro formulário não conta NULL valores.

Ou seja, desde que id não pode ser NULL - como indicado no topo. id deve realmente ser a PRIMARY KEY , que é implementado com um índice B-tree exclusivo internamente de qualquer maneira, e todas as colunas - apenas id aqui - são NOT NULL implicitamente. Ou pelo menos NOT NULL . Um UNIQUE INDEX não se qualifica totalmente como substituição, ainda permite NULL valores que não são considerados iguais e são permitidos várias vezes. Ver:

Além disso, os índices não são úteis aqui, pois todas as linhas precisam ser lidas de qualquer maneira. Então isso nunca vai ser muito barato. Mas 62 mil linhas não é uma contagem de linhas incapacitante de forma alguma - a menos que você tenha um grande número de chaves no jsonb coluna.

As opções restantes para acelerá-lo:

  1. Normalize seu projeto. Desaninhar documentos JSON não é gratuito.

  2. Mantenha uma visão materializada. A viabilidade e os custos dependem fortemente de seus padrões de gravação.

É aí que os índices podem desempenhar um papel novamente ...