Explicação do JSONB introduzida pelo PostgreSQL

345

O PostgreSQL acabou de lançar o JSONB e já está em alta nas notícias de hackers . Seria ótimo se alguém pudesse explicar como é diferente do Hstore e JSON anteriormente presentes no PostgreSQL. Quais são suas vantagens e limitações e quando alguém deve considerar usá-lo?

Peeyush
fonte
4
De PGCon2014: youtube.com/…
msanford 13/06
5
O URL do @CraigRinger não é preciso o suficiente, agora, um ano depois, nem sequer aponta o suficiente para o conteúdo relacionado ao JSONB.
22615 berkus
2
@berkus Eu pensei que tinha um link para o post específico. Que frustrante.
Craig Ringer
11
Aponta para o vídeo específico.
Talonx

Respostas:

455

Primeiro, hstoreé um módulo contrib, que permite armazenar apenas pares chave => valor, onde chaves e valores podem ser apenas texts (no entanto, os valores também podem ser sql NULLs).

Ambos json& jsonbpermite que você armazene um valor JSON válido (definido em suas especificações ).

F.ex. estes são representações JSON válidos: null, true, [1,false,"string",{"foo":"bar"}], {"foo":"bar","baz":[null]}- hstoreé apenas um pequeno subconjunto comparado ao que JSON é capaz (mas se você só precisa este subconjunto, está tudo bem).

A única diferença entre json& jsonbé o armazenamento:

  • json é armazenado em seu formato de texto sem formatação, enquanto
  • jsonb é armazenado em alguma representação binária

Existem três consequências principais disso:

  • jsonbnormalmente ocupa mais espaço em disco para armazenar do que json(às vezes não)
  • jsonb leva mais tempo para construir a partir de sua representação de entrada do que json
  • jsonas operações levam muito mais tempo do que jsonb(e a análise também precisa ser feita sempre que você realiza alguma operação com um jsonvalor digitado)

Quando jsonbestará disponível com uma versão estável, haverá dois casos de uso principais, quando você poderá selecionar facilmente entre eles:

  1. Se você trabalha apenas com a representação JSON em seu aplicativo, o PostgreSQL é usado apenas para armazenar e recuperar essa representação, você deve usá-lo json.
  2. Se você realiza muitas operações no valor JSON no PostgreSQL ou usa a indexação em algum campo JSON, deve usar jsonb.
pozs
fonte
11
oi, uma vez que tem representação binária, por jsonbque não suporta isso? UPDATE test SET data->'a' = 123 WHERE id = 1;DeCREATE TABLE test(id SERIAL PRIMARY KEY, data JSONB);
Kokizzu 28/11
11
Kokizzu, é possível na 9.5. Você está em
Home
11
Só para acrescentar, uma das razões que você também pode usar jsonmais jsonbé se por razões de legado seu código consumindo sua jsoné dependente da ordenação dos jsoncampos e eles não podem ser reordenadas.
precisa saber é o seguinte
4
Como, pelas razões herdadas: no JSON, não há diferença semântica, se os pares de valores-chave de um objeto (tabela, mapa, hash, seja lá o que for chamado na linguagem host) são ordenados de maneira diferente. Se você confiar nisso, estará realmente usando algo diferente do JSON. - Para textvs json.: o último vem com validação JSON, portanto, com JSON inválido, ele falha apenas na inserção, em vez de toda vez que seu aplicativo lê (porque obtém uma representação inválida). Além disso, você pode transmitir com segurança o último para jsonbdentro do banco de dados.
pozs 21/03
2
Este é um ótimo post sobre como explicar os detalhes de implementação do JSONB ( pgeoghegan.blogspot.com/2014/03/what-i-think-of-jsonb.html )
manugupt1
131

Peeyush:

A resposta curta é:

  • Se você estiver fazendo muita manipulação JSON no PostgreSQL, como classificação, fatia, emenda, etc., você deve usar o JSONB por motivos de velocidade.
  • Se você precisar de pesquisas indexadas para pesquisas de chave arbitrárias no JSON, deverá usar o JSONB.
  • Se você não estiver fazendo nenhuma das opções acima, provavelmente deverá usar JSON.
  • Se você precisar preservar as chaves, espaços em branco e chaves duplicadas, use JSON.

Para uma resposta mais longa, você precisará esperar que eu faça uma redação completa do "HowTo" mais próxima da versão 9.4.

FuzzyChef
fonte
74

Uma explicação simples da diferença entre json e jsonb ( imagem original de PostgresProfessional ):

SELECT '{"c":0,   "a":2,"a":1}'::json, '{"c":0,   "a":2,"a":1}'::jsonb;

          json          |        jsonb 
------------------------+--------------------- 
 {"c":0,   "a":2,"a":1} | {"a": 1, "c": 0} 
(1 row)
  • json: armazenamento textual «como está»
  • jsonb: sem espaços em branco
  • jsonb: nenhuma chave duplicada, última vitória da chave
  • jsonb: chaves são ordenadas

Mais em vídeo discursivo e apresentação de slides por desenvolvedores jsonb. Eles também introduziram o JsQuery , pg.extension fornece uma poderosa linguagem de consulta jsonb

ChelowekKot
fonte
11
Obrigado, eu substituí-lo para texto
ChelowekKot
55
  • hstore é mais um tipo de armazenamento de "coluna ampla", é um dicionário simples (não aninhado) de pares de valores-chave, sempre armazenados em um formato binário razoavelmente eficiente (uma tabela de hash, daí o nome).
  • jsonarmazena documentos JSON como texto, realizando a validação quando os documentos são armazenados e analisando-os na saída, se necessário (por exemplo, acessar campos individuais); deve suportar toda a especificação JSON. Como todo o texto JSON é armazenado, sua formatação é preservada.
  • jsonbutiliza atalhos por motivos de desempenho: os dados JSON são analisados ​​na entrada e armazenados no formato binário, as ordens de chave nos dicionários não são mantidas e as chaves duplicadas. O acesso a elementos individuais no campo JSONB é rápido, pois não requer a análise do texto JSON o tempo todo. Na saída, os dados JSON são reconstruídos e a formatação inicial é perdida.

Na IMO, não há razão significativa para não usar jsonbquando estiver disponível, se você estiver trabalhando com dados legíveis por máquina.

Ivan Voras
fonte
24

JSONB é uma versão "melhor" do JSON.

Vejamos um exemplo:

SELECT '{"c":0,   "a":2,"a":1}'::json, '{"c":0,   "a":2,"a":1}'::jsonb;
          json          |        jsonb 
------------------------+--------------------- 
 {"c":0,   "a":2,"a":1} | {"a": 1, "c": 0} 
(1 row)
  1. O JSON armazena espaço em branco; é por isso que podemos ver espaços quando a chave "a" é armazenada, enquanto o JSONB não.
  2. JSON armazena todos os valores da chave. É por isso que você pode ver vários valores (2 e 1) na chave "a", enquanto JSONB apenas "armazena" o último valor.
  3. JSON mantém a ordem na qual os elementos são inseridos, enquanto JSONB mantém a ordem "classificada".
  4. Os objetos JSONB são armazenados como binário descompactado em oposição a "dados brutos" no JSON, em que nenhuma análise de dados é necessária durante a recuperação.
  5. O JSONB também suporta indexação, o que pode ser uma vantagem significativa.

Em geral, deve-se preferir o JSONB, a menos que haja necessidades especializadas, como suposições herdadas sobre a ordem de chaves de objetos.

subodhkarwa
fonte
13

Eu estava no pgopen hoje, os benchmarks são muito mais rápidos que o mongodb, acredito que foi cerca de 500% mais rápido para os selects. Praticamente tudo foi mais rápido, pelo menos em 200%, quando comparado ao mongodb. No momento, uma exceção é uma atualização que exige reescrever completamente toda a coluna json com a qual o mongodb lida melhor.

A indexação do gin no jsonb parece incrível.

Além disso, o postgres persistirá tipos de jsonb internamente e basicamente corresponderá a isso com tipos como numérico, texto, booleano etc.

Associações também serão possíveis usando jsonb

Adicione o PLv8 para procedimentos armazenados e isso basicamente será um sonho para os desenvolvedores do node.js.

Sendo armazenado como binário, o jsonb também removerá todo o espaço em branco, alterará a ordem das propriedades e removerá as propriedades duplicadas usando a última ocorrência da propriedade.

Além do índice, ao consultar uma coluna jsonb em contraste com uma coluna json, o postgres não precisa executar a funcionalidade para converter o texto em json em todas as linhas, o que provavelmente economizará muito tempo sozinho.

John
fonte
7

Em relação às diferenças entre jsone jsonbtipos de dados, vale ressaltar a explicação oficial:

O PostgreSQL oferece dois tipos para armazenar dados JSON: jsone jsonb. Para implementar mecanismos de consulta eficientes para esses tipos de dados, o PostgreSQL também fornece o tipo de dados jsonpath descrito na Seção 8.14.6 .

Os tipos de dados jsone jsonbaceitam conjuntos de valores quase idênticos como entrada. A principal diferença prática é a da eficiência. O jsontipo de dados armazena uma cópia exata do texto de entrada, cujas funções de processamento devem analisar novamente a cada execução; enquanto os jsonbdados são armazenados em um formato binário decomposto, que torna a entrada um pouco mais lenta devido à sobrecarga adicional da conversão, mas significativamente mais rápida de processar, pois não é necessária nenhuma nova correção. jsonbtambém suporta indexação, o que pode ser uma vantagem significativa.

Como o jsontipo armazena uma cópia exata do texto de entrada, preservará o espaço em branco semanticamente insignificante entre os tokens, bem como a ordem das chaves nos objetos JSON. Além disso, se um objeto JSON dentro do valor contiver a mesma chave mais de uma vez, todos os pares chave / valor serão mantidos. (As funções de processamento consideram o último valor como o operacional.) Por outro lado, jsonbnão preserva o espaço em branco, não preserva a ordem das chaves do objeto e não mantém as chaves duplicadas do objeto. Se chaves duplicadas forem especificadas na entrada, apenas o último valor será mantido.

Em geral, a maioria dos aplicativos deve preferir armazenar dados JSON como jsonb, a menos que haja necessidades bastante especializadas, como suposições herdadas sobre a ordem de chaves de objetos.

O PostgreSQL permite apenas uma codificação de conjunto de caracteres por banco de dados. Portanto, não é possível que os tipos JSON estejam em conformidade rígida com a especificação JSON, a menos que a codificação do banco de dados seja UTF8. Tentativas de incluir diretamente caracteres que não podem ser representados na codificação do banco de dados falharão; por outro lado, serão permitidos caracteres que possam ser representados na codificação do banco de dados, mas não no UTF8.

Fonte: https://www.postgresql.org/docs/current/datatype-json.html

Dinei
fonte
6

Tanto quanto eu posso dizer,

  • hstore como existe atualmente (no Postgresql 9.3) não permite aninhar outros objetos e matrizes como os valores de seus pares chave / valor. no entanto, um futuro patch hstore permitirá o aninhamento. esse patch não estará na versão 9.4 e pode não ser incluído tão cedo.

  • O json, como ele existe atualmente , permite o aninhamento, mas é baseado em texto e não permite a indexação; portanto, é "lento"

  • O jsonb que será lançado com a versão 9.4 terá os recursos de aninhamento atuais do json, bem como a indexação GIN / GIST do hstore, por isso será rápido

As pessoas que trabalham no postgresql 9.4 parecem dizer que o novo e rápido tipo jsonb agradará as pessoas que escolheriam usar um repositório de dados noSQL como o MongoDB, mas agora podem combinar um banco de dados relacional com dados não estruturados passíveis de consulta sob o mesmo teto

http://www.databasesoup.com/2014/02/why-hstore2jsonb-is-most-important.html

Os benchmarks do postgresql 9.4 jsonb parecem estar no mesmo nível ou em alguns casos mais rápidos que o MongoDB

http://texture.io/alphabetum/postgresql-incl-hstore-vs-mongodb

erik swedberg
fonte
6

Outra diferença importante, que não foi mencionada em nenhuma resposta acima, é que não há operador de igualdade para o jsontipo, mas existe um para jsonb.

Isso significa que você não pode usar a DISTINCTpalavra-chave ao selecionar esse jsontipo e / ou outros campos de uma tabela (você pode usar DISTINCT ON, mas isso nem sempre é possível devido a casos como esse ).

vlasiak
fonte