JSONB con indexación frente a hstore

28

Estoy tratando de decidir sobre el diseño de la base de datos, con la menor cantidad de suposiciones (con respecto a cómo evoluciona realmente la aplicación web) en esta etapa.

Como primer paso, entendiendo que las UNIONES son caras, estoy considerando una pequeña cantidad de tablas monolíticas en lugar de una gran cantidad de tablas más pequeñas normalizadas. Como segundo punto, estoy confundido entre usar hstore vs. tablas regulares vs. JSONB (con indexación GiST).

AFAIK (no dude en corregir):

  1. En general, en Postgres, se sabe que hstore funciona mejor que otros tipos de datos. Esta presentación de FOSDEM PGDAY tiene algunas estadísticas interesantes (en la segunda mitad de las diapositivas). https://wiki.postgresql.org/images/b/b4/Pg-as-nosql-pgday-fosdem-2013.pdf

  2. Una ventaja con hstore es la indexación rápida (GiN o GiST). Sin embargo, con JSONB, la indexación GiN y GiST también se puede aplicar a los datos JSON.

  3. Este blog de un profesional del 2do Cuadrante dice "En este punto, probablemente valga la pena reemplazar el uso de hstore con jsonb en todas las aplicaciones nuevas" (desplazarse hasta el final): http://blog.2ndquadrant.com/postgresql-anti-patterns-unnecessary -jsonhstore-dynamic-columnas /

Entonces me gustaría decidir sobre lo siguiente:

  1. Para la parte principal (estructurada) de los datos: ¿debería ir en un par de tablas relacionales (relativamente grandes con muchas columnas), o debería ser un número de almacenes de valores clave usando hstore?
  2. Para los datos ad hoc (aportados por el usuario / no estructurados), ¿deben estar en JSON o en almacenes de valores de clave ad hoc en hstore (con las claves almacenadas en una de las tablas relacionales principales)?
Yogesch
fuente
77
Las uniones no son caras. ¿Quién te lo dijo? Como básicamente todo el concepto de bases de datos relacionales gira en torno a las uniones (desde un punto de vista práctico), estos productos son muy buenos para unirse. La forma normal de pensar es comenzar con estructuras correctamente normalizadas y entrar en desnormalizaciones sofisticadas y cosas similares cuando el rendimiento realmente lo necesita en el lado de la lectura. JSON(B)y hstore(y EAV) son buenos para datos con estructura desconocida.
dezso
66
@Yogesch esos enlaces contienen algunas cosas interesantes y tremendamente contradictorias :) Como una moraleja, parece que MySQL es (era) malo para las uniones, y la gente de NoSQL tiende a generalizar esta noción sin ninguna base real de hecho. Por otro lado, Aaron y Max son sensibles a esa palabra p: su amplio uso muestra cómo los hablantes no nativos (incluido yo mismo) usan felizmente la palabra incorrecta.
dezso
44
@Yogesch de manera realista, estoy seguro de que hay una fuente en Internet para "probar" cualquier cosa, al igual que cualquier texto religioso puede usarse para justificar las atrocidades (como se muestra dramáticamente en la historia). Es cierto que cuanto menos trabajo haga, menos cuesta, pero siempre hay algo de compensación .
Erik
44
@Yogesch: Evitar las uniones es importante para las operaciones con mucha lectura en las que conoce el patrón de acceso a los datos de antemano, por lo que puede colocar de forma segura todos los datos que necesita en una sola fila. Sin embargo, esto hace que otras uniones sean potencialmente más costosas. ¿Quién puede decir que no necesitará unir los datos de muchas maneras diferentes para responder varias preguntas? Ahora vamos a descender simplemente a la teoría del modelado de datos relacionales ...
Chris
55
@Yogesch En mi práctica, con las bases de datos, el cuello de botella rara vez es la RAM o la CPU, pero es E / S; de esta manera, evitar el almacenamiento de datos redundantes sigue siendo algo importante. Como dice Chris, si siempre ve sus datos de una sola manera, esto podría valer la pena. Si no, está allí con una gran cantidad de datos voluminosos y muy poco flexibles.
dezso

Respuestas:

41

Las bases de datos relacionales están diseñadas en torno a las combinaciones y optimizadas para hacerlo bien.

A menos que tenga una buena razón para no usar un diseño normalizado, use un diseño normalizado.

jsonby cosas así hstoreson buenas para cuando no puede usar un modelo de datos normalizado, como cuando el modelo de datos cambia rápidamente y está definido por el usuario.

Si puede modelarlo relacionalmente, modele relacionalmente. Si no puede, considere json, etc. Si elige entre json / jsonb / hstore, generalmente elija jsonb a menos que tenga una razón para no hacerlo.

Eso es lo que dije en mi publicación de blog , que aborda solo este tema. Por favor lea la publicación completa . El párrafo que citó señala que si está eligiendo una estructura dinámica , debe elegir jsonb en lugar de hstore, pero el resto de la publicación del blog es sobre por qué generalmente debería preferir modelar relacionalmente si puede.

Asi que. Modele la parte estructurada principal relacionalmente. Si las tablas son realmente anchas con muchas columnas, esto podría ser una señal de que se requiere una mayor normalización. No tengas miedo de las uniones. Aprende a amar se une. Unir muchas tablas pequeñas a menudo será más rápido que consultar y mantener tablas desnormalizadas grandes. Desormalice solo si lo necesita para casos específicos, y preferiblemente a través de vistas materializadas ... pero no lo haga hasta que sepa que lo necesita y tenga un problema concreto que resolver.

Para los datos aportados por los usuarios que son de forma libre y no estructurados, use jsonb. Debería funcionar tan bien como hstore, pero es más flexible y más fácil de trabajar.

Una cosa relevante para entender: los índices GiST y GIN como los utilizados en jsonb son generalmente mucho menos eficientes que un índice b-tree simple. Son más flexibles, pero un índice b-tree en una columna normal casi siempre será mucho, mucho más rápido.

Craig Ringer
fuente
Muchas gracias Craig, ahora entiendo mucho mejor y sé qué hacer. Una pregunta de seguimiento: si estoy almacenando algo como me gusta o seguidores en un formato de dos columnas (post_id y user_id, para me gusta ), ¿es mejor usar una tabla relacional con dos columnas o un hstore? (No me importa convertir esto en una nueva pregunta)
Yogesch
55
@Yogesch Suena como una tabla de unión m: n estándar con un formato estable y consistente. La pregunta siempre debe ser "¿hay una buena razón por la que no debería hacer esto de la manera relacional habitual para este caso en particular?".
Craig Ringer
hstorees obsoleto. Uso jsonb.
peligro89
2
@ danger89 En realidad, no está en desuso formalmente, aunque ya no creo que haya ninguna razón para usarlo a favor de jsonb. En cualquier caso ... eso es como perder el punto. La pregunta es si modelar relacionalmente o usar un tipo de datos estructurado.
Craig Ringer