JSONB com indexação vs. hstore

28

Estou tentando decidir sobre o design do banco de dados, com o mínimo possível de suposições (sobre como o aplicativo da Web realmente evolui) neste estágio.

Como primeiro passo, entendendo que JOINS são caros, estou considerando um pequeno número de tabelas monolíticas em oposição a um grande número de tabelas menores normalizadas. Como segundo ponto, estou confuso entre o uso de hstore e tabelas regulares e JSONB (com indexação GiST).

AFAIK (sinta-se à vontade para corrigir):

  1. Geralmente, no Postgres, o hstore é conhecido por ter um desempenho melhor que outros tipos de dados. Esta apresentação do FOSDEM PGDAY tem algumas estatísticas interessantes (na segunda metade dos slides). https://wiki.postgresql.org/images/b/b4/Pg-as-nosql-pgday-fosdem-2013.pdf

  2. Uma vantagem do hstore é a indexação rápida (GiN ou GiST). No entanto, com a indexação JSONB, GiN e GiST também pode ser aplicada aos dados JSON.

  3. Este blog de um profissional do 2º Quadrante diz "Nesse momento, provavelmente vale a pena substituir o uso do hstore pelo jsonb em todos os novos aplicativos" (role até o final): http://blog.2ndquadrant.com/postgresql-anti-patterns-unnecessary -jsonhstore-dynamic-columns /

Então, eu gostaria de decidir o seguinte:

  1. Para a parte principal (estruturada) dos dados: ela deve estar em algumas tabelas relacionais (relativamente grandes com muitas colunas) ou deve haver um número de armazenamentos de valores-chave usando hstore?
  2. Para os dados ad hoc (contribuído / não estruturado pelo usuário), ele deve estar em JSON ou armazenamentos de valor de chave ad hoc no hstore (com as chaves armazenadas em uma das principais tabelas relacionais)?
Yogesch
fonte
7
Associações não são caras. Quem te disse isso? Como basicamente todo o conceito de bancos de dados relacionais gira em torno de junções (de um ponto de vista prático), esses produtos são muito bons em participar. O modo de pensar normal começa com estruturas adequadamente normalizadas e entra em desnormalizações sofisticadas e coisas semelhantes quando o desempenho realmente precisa disso no lado da leitura. JSON(B)e hstore(e EAV) são bons para dados com estrutura desconhecida.
Dez22
6
@Yogesch esses links contêm algumas coisas interessantes e contraditórias :) Como moral, parece que o MySQL é (era) ruim em junções, e as pessoas do NoSQL tendem a generalizar essa noção sem nenhuma base factual real. Por outro lado, Aaron e Max são sensíveis a essa palavra-p - seu amplo uso mostra como falantes não-nativos (inclusive eu) usam alegremente a palavra errada.
Dez22
4
@Yogesch, realisticamente, tenho certeza de que existe uma fonte na Internet para "provar" qualquer coisa, assim como qualquer texto religioso pode ser usado para justificar atrocidades (como mostrado dramaticamente ao longo da história). É verdade que, quanto menos trabalho você faz, menos isso custa, mas sempre há uma troca .
Erik
4
@Yogesch: Evitar junções é importante para operações de leitura pesada em que você conhece o padrão de acesso a dados com antecedência e, portanto, pode colocar com segurança todos os dados necessários em uma única linha. No entanto, isso torna outras junções potencialmente mais caras. Quem pode dizer que você não precisará juntar os dados de muitas maneiras diferentes para responder a várias perguntas? Agora vamos simplesmente descer a teoria de modelagem de dados relacional ...
Chris
5
@Yogesch Na minha prática, com bancos de dados, o gargalo raramente é a RAM ou a CPU, mas é de E / S - dessa forma, evitar o armazenamento de dados redundantes ainda é uma coisa importante. Como Chris diz, se você sempre vê seus dados de apenas uma maneira, isso pode valer a pena. Caso contrário, você estará lá com um grande volume de dados altamente flexível.
Dez22

Respostas:

41

Os bancos de dados relacionais são projetados em torno de junções e otimizados para fazê-los bem.

A menos que você tenha um bom motivo para não usar um design normalizado, use um design normalizado.

jsonbe coisas hstoreboas para quando você não pode usar um modelo de dados normalizado, como quando o modelo de dados muda rapidamente e é definido pelo usuário.

Se você pode modelá-lo relacionalmente, modele-o relacionalmente. Se não puder, considere json, etc. Se você estiver escolhendo entre json / jsonb / hstore, geralmente escolha jsonb, a menos que tenha um motivo para não fazê-lo.

Foi o que eu disse no meu blog , que aborda apenas esse tópico. Por favor, leia o post completo . O parágrafo que você citou indica que, se você estiver escolhendo uma estrutura dinâmica, deverá escolher jsonb em vez de hstore, mas o restante da postagem do blog é sobre o motivo pelo qual você geralmente prefere modelar de forma relacional, se puder.

Tão. Modele a parte estruturada principal de forma relacional. Se as tabelas forem realmente amplas e com muitas colunas, isso pode ser um sinal de que é necessária uma normalização adicional. Não tenha medo de junções. Aprenda a amar as junções. A junção de muitas tabelas pequenas geralmente será mais rápida do que a consulta e a manutenção de grandes tabelas desnormalizadas. Desnormalize apenas se for necessário para casos específicos e, de preferência, através de visualizações materializadas ... mas não faça isso até que você saiba que precisa e tenha um problema concreto real para resolver.

Para dados contribuídos pelo usuário de forma livre e não estruturada, use jsonb. Ele deve ter um desempenho tão bom quanto o hstore, mas é mais flexível e fácil de trabalhar.

Uma coisa relevante a entender: os índices GiST e GIN, como os usados ​​no jsonb, geralmente são muito menos eficientes do que um índice simples da árvore b. Eles são mais flexíveis, mas um índice de árvore b em uma coluna normal quase sempre será muito, muito mais rápido.

Craig Ringer
fonte
Muito obrigado Craig, agora tenho um entendimento muito melhor e sei o que fazer. Uma pergunta de acompanhamento: se estou armazenando algo como gostos ou seguidores em um formato de duas colunas (post_id e user_id, para gostos ), é melhor usar uma tabela relacional com duas colunas ou um hstore? (Eu não me importo de fazer isso em uma nova pergunta)
Yogesch
5
@Yogesch Parece uma tabela de junção m: n padrão-bog com um formato consistente e estável. A pergunta deve sempre ser "existe uma boa razão para eu não fazer isso da maneira relacional usual para esse caso em particular?".
Craig Ringer
hstoreestá obsoleto. Use jsonb.
danger89
2
@ danger89 Na verdade, não é formalmente reprovado, embora eu ache que não há mais motivo para usá-lo em favor do jsonb. De qualquer forma ... isso está meio errado. A questão é se deve modelar de forma relacional ou usar um tipo de dados estruturado.
Craig Ringer