Ir al contenido principal
BlogBases de datosAprovechamiento de las capacidades NoSQL en PostgreSQL

Aprovechamiento de las capacidades NoSQL en PostgreSQL

Imagen con un símbolo que representa una base de datos conectada a otras bases de datos y el texto Harnessing NoSQL Capabilities in PostgreSQL en la parte inferior.

Los almacenes de documentos NoSQL pueden ser ideales para gestionar grandes cantidades de datos no estructurados. Sin embargo, algunas organizaciones trabajan con datos no estructurados, pero todavía quieren las capacidades que vienen con las bases de datos SQL tradicionales. Por ejemplo, los medios de comunicación o las agencias de contenidos informativos pueden gestionar sitios web con mucho tráfico centrados en grandes cantidades de contenido de texto e imágenes. Aunque necesiten almacenar estos datos no estructurados, quizá no necesiten los esquemas flexibles o la escalabilidad horizontal que ofrecen las bases de datos NoSQL. En su lugar, necesitan la facilidad de gestión de bases de datos y la coherencia que ofrece una base de datos relacional como PostgreSQL.

¿Es posible obtener lo mejor de ambos mundos? Sí.

Con sus tipos de datos destinados a soportar datos no estructurados, PostgreSQL ofrece un medio feliz, lo que le permite aprovechar las capacidades NoSQL dentro de una base de datos relacional que es rentable y fácil de manejar. En este artículo, veremos cómo puede utilizar los tipos de datos HStore y JSONB en PostgreSQL para trabajar con datos no estructurados.

Antes de entrar en materia, veamos brevemente las principales diferencias entre las bases de datos SQL y NoSQL.

Entendiendo SQL frente a NoSQL

Las bases de datos SQL y NoSQL tienen cada una sus puntos fuertes y débiles. Tomar una decisión informada sobre cuál satisfará mejor sus necesidades de datos depende de una sólida comprensión de sus diferencias.

Las bases de datos SQL (relacionales), como PostgreSQL y MySQL, representan los datos con una estructura clara y predecible en tablas, filas y columnas. Se adhieren a las propiedades ACID (atomicidad, consistencia, aislamiento y durabilidad), que proporcionan una base sólida para la integridad de los datos al garantizar que las transacciones de la base de datos se procesan de forma fiable.

Las bases de datos SQL brillan allí donde la coherencia y la integridad de los datos son cruciales, como cuando se trata de consultas complejas y sistemas transaccionales (como ocurre con las aplicaciones financieras).

Por el contrario, las bases de datos NoSQL (almacenes de documentos) se adaptan a conjuntos de datos grandes y variados que no son necesariamente adecuados para la representación tabular. Algunos ejemplos de bases de datos NoSQL son MongoDB, Cassandra y Couchbase. Las bases de datos NoSQL trabajan con esquemas flexibles, lo que permite que las estructuras de datos evolucionen con el tiempo. También admiten la escalabilidad horizontal, distribuyendo los datos entre varios servidores para mejorar la gestión de grandes cargas de datos y un tráfico elevado.

Las bases de datos NoSQL se utilizan a menudo en aplicaciones en las que la escalabilidad es crucial, como para manejar grandes cantidades de datos en aplicaciones en tiempo real o grandes modelos lingüísticos (LLM). Las bases de datos NoSQL también son beneficiosas cuando se trata de estructuras de datos variadas y en evolución, ya que permiten a las organizaciones adaptarse a medida que cambian sus necesidades de datos.

¿Por qué utilizar PostgreSQL como almacén de documentos?

PostgreSQL es una base de datos relacional, por lo que puede parecer poco convencional considerarla una opción para satisfacer las necesidades NoSQL. Sin embargo, su situación puede tener un caso fuerte para el uso de PostgreSQL como un almacén de documentos.

Si sus necesidades de almacenamiento de datos son diversas -requieren tanto almacenamiento de datos estructurados y conformes con ACID como almacenamiento de documentos flexible y sin esquemas- entonces puede aprovechar PostgreSQL para combinar modelos relacionales y no relacionales. O, tal vez usted quiere ciertas capacidades NoSQL pero también quiere las garantías de consistencia de datos que vienen con las propiedades ACID. Por último, como tecnología madura con una comunidad activa, PostgreSQL ofrece soporte SQL completo, indexación avanzada y búsqueda de texto completo. Estas características, combinadas con sus capacidades NoSQL, hacen de PostgreSQL una solución versátil de almacenamiento de datos.

Limitaciones del uso de PostgreSQL para datos de estilo NoSQL

A pesar de su versatilidad, PostgreSQL tiene ciertas limitaciones en comparación con las bases de datos NoSQL tradicionales. Aunque PostgreSQL puede escalarse verticalmente, no admite de forma inherente el escalado horizontal o los datos distribuidos con fragmentación automática, características que suelen ofrecer las bases de datos NoSQL. PostgreSQL tampoco ofrece optimizaciones para ciertas estructuras de datos NoSQL como almacenes de columnas anchas o bases de datos gráficas. Por último, PostgreSQL no ofrece consistencia sintonizable para optimizar el rendimiento, que puede obtener de algunas bases de datos NoSQL.

Al considerar el uso de PostgreSQL para grandes conjuntos de datos no estructurados, tenga en cuenta que estas limitaciones pueden afectar al rendimiento y a su capacidad de ampliación. Además, mezclar operaciones de datos SQL y NoSQL introduce complejidad. Una planificación cuidadosa y la comprensión de ambos paradigmas le ayudarán a evitar posibles escollos.

Sin embargo, con la comprensión y el caso de uso adecuados, PostgreSQL puede servir como una poderosa herramienta, proporcionando lo mejor de ambos mundos, SQL y NoSQL.

HStore y JSONB en PostgreSQL

Al considerar las posibilidades de usar PostgreSQL como una solución NoSQL, nos encontramos con tres tipos de datos que ofrecen funcionalidad similar a NoSQL, pero cada uno tiene características y casos de uso únicos.

  1. HStore: Este tipo de datos permite almacenar pares clave-valor en un único valor PostgreSQL. Es útil para almacenar datos semiestructurados que no tienen un esquema fijo.
  2. JSONB: Se trata de una representación binaria de datos de tipo JSON. Puede almacenar estructuras más complejas en comparación con HStore y soporta todas las capacidades de JSON. JSONB es indexable, por lo que es una buena opción para grandes cantidades de datos.
  3. JSON: Es similar a JSONB, aunque carece de muchas de las capacidades y eficiencias de JSONB. El tipo de datos JSON almacena una copia exacta del texto de entrada, que incluye espacios en blanco y claves duplicadas.

Mencionamos el tipo de datos JSON como una opción válida para almacenar datos con formato JSON cuando no necesitas las capacidades completas proporcionadas por JSONB. Sin embargo, nuestro enfoque principal para el resto de este artículo será HStore y JSONB.

HStore

La documentación de PostgreSQL describe HStore como útil cuando se tienen "filas con muchos atributos que rara vez se examinan, o datos semiestructurados". Antes de poder trabajar con el tipo de datos HStore, asegúrese de habilitar la extensión HStore:

> CREATE EXTENSION hstore;

HStore se representa como cero o más clave => valor separados por comas. El orden de los pares no es significativo ni se conserva de forma fiable en la salida.

> SELECT 'foo => bar, prompt => "hello world", pi => 3.14'::hstore;
                      hstore                       
-----------------------------------------------------
"pi"=>"3.14", "foo"=>"bar", "prompt"=>"hello world"
(1 row)

Cada clave HStore es única. Si una declaración HStore se hace con claves duplicadas, sólo uno de los duplicados se almacenará, y no hay ninguna garantía sobre cuál será.

> SELECT 'key => value1, key => value2'::hstore;
    hstore     
-----------------
"key"=>"value1"
(1 row)

Con su estructura plana clave-valor, HStore ofrece simplicidad y rapidez de consulta, por lo que es ideal para escenarios sencillos. Sin embargo, HStore solo admite datos de texto y no admite datos anidados, por lo que resulta limitado para estructuras de datos complejas.

Por otro lado, JSONB puede manejar una mayor variedad de tipos de datos.

JSONB

El tipo de datos JSONB acepta texto de entrada con formato JSON y luego lo almacena en un formato binario descompuesto. Aunque esta conversión hace que la entrada sea ligeramente lenta, el resultado es un procesamiento rápido y una indexación eficiente. JSONB no conserva los espacios en blanco ni el orden de las claves de los objetos.

> SELECT '{"foo": "bar", "pi": 3.14, "nested": { "prompt": "hello", "count": 5 } }'::jsonb;
                                jsonb                                
-----------------------------------------------------------------------
{"pi": 3.14, "foo": "bar", "nested": {"count": 5, "prompt": "hello"}}
(1 row)

Si se dan claves de objeto duplicadas, se mantiene el último valor.

> SELECT '{"key": "value1", "key": "value2"}'::jsonb;
      jsonb      
-------------------
{"key": "value2"}
(1 row)

Dado que JSONB admite estructuras complejas y capacidades JSON completas, es la opción ideal para datos complejos o anidados, preferible a HStore o JSON. Sin embargo, el uso de JSONB introduce cierta sobrecarga de rendimiento y un mayor uso de almacenamiento en comparación con HStore.

Ejemplos prácticos: Trabajar con HStore y JSONB

Veamos algunos ejemplos prácticos para demostrar cómo trabajar con estos tipos de datos. Veremos la creación de tablas, las consultas y operaciones básicas y la indexación.

Operaciones básicas de HStore

Como lo haría con cualquier otro tipo de datos, puede definir campos en su tabla de datos PostgreSQL como un tipo de datos HStore.

> CREATE TABLE articles (    id serial primary key,    title varchar(64),    meta hstore  );

Insertar un registro con un atributo HStore tiene el siguiente aspecto:

> INSERT INTO articles (title, meta)
  VALUES (
    'Data Types in PostgreSQL',
    'format => blog, length => 1350, language => English, license => "Creative Commons"');

> SELECT * FROM articles;
id |          title           | meta                                     ----+--------------------------+------------------------------------------  1 | Data Types in PostgreSQL | "format"=>"blog", "length"=>"1350", "license"=>"Creative Commons", "language"=>"English"(1 row)

Con los campos HStore, puede obtener pares clave-valor específicos del campo especificados por las claves que proporcione:

> SELECT title,          meta -> 'license' AS license,         meta -> 'format' AS format  FROM articles;
              title              |     license      |   format  
---------------------------------+------------------+------------
Data Types in PostgreSQL        | Creative Commons | blog
Advanced Querying in PostgreSQL | None             | blog
Scaling PostgreSQL              | MIT              | blog
PostgreSQL Fundamentals         | Creative Commons | whitepaper
(4 rows)

También puede consultar con criterios basados en valores específicos dentro de un campo HStore.

> SELECT id, title FROM articles WHERE meta -> 'license' = 'Creative Commons';

id |          title          
----+--------------------------
  1 | Data Types in PostgreSQL
  4 | PostgreSQL Fundamentals
(2 rows)

Es posible que a veces sólo desee consultar filas que contengan una clave específica en el campo HStore. Por ejemplo, la siguiente consulta sólo devuelve filas en las que el meta HStore contiene la clave de nota. Para ello, utilice el operador ?

> SELECT title, meta->'note' AS note FROM articles WHERE meta ? 'note';
              title              |      note      
---------------------------------+-----------------
PostgreSQL Fundamentals         | hold for review
Advanced Querying in PostgreSQL | needs edit
(2 rows)

Aquí puede encontrar una lista de operadores y funciones HStore útiles. Por ejemplo, puede extraer las claves de un HStore a un array, o puede convertir un HStore a una representación JSON.

> SELECT title, akeys(meta) FROM articles where id=1;
          title           |              akeys              
--------------------------+----------------------------------
Data Types in PostgreSQL | {format,length,license,language}
(1 row)

> SELECT title, hstore_to_json(meta) FROM articles where id=1;
          title           |            hstore_to_json
--------------------------+------------------------------------------------
Data Types in PostgreSQL | {"format": "blog", "length": "1350", "license": "Creative Commons", "language": "English"}
(1 row)

Operaciones JSONB básicas

Trabajar con el tipo de datos JSONB en PostgreSQL es sencillo. La creación de tablas y la inserción de registros tienen este aspecto:

> CREATE TABLE authors (id serial primary key, name varchar(64), meta jsonb);

> INSERT INTO authors (name, meta)  VALUES    ('Adam Anderson',     '{ "active":true, "expertise": ["databases", "data science"], "country": "UK" }');

Tenga en cuenta que el campo meta jsonb se proporciona como una cadena de texto en formato JSON. PostgreSQL se quejará si el valor proporcionado no es un JSON válido.

> INSERT INTO authors (name, meta)  VALUES ('Barbara Brandini', '{ "this is not valid JSON" }');
ERROR:  invalid input syntax for type json

A diferencia del tipo HStore, JSONB admite datos anidados.

> INSERT INTO authors (name, meta)  VALUES ('Barbara Brandini',          '{ "active":true,             "expertise": ["AI/ML"],             "country": "CAN",             "contact": {               "email": "barbara@example.com",               "phone": "111-222-3333"             }           }');

De forma similar a HStore, los campos JSONB pueden recuperarse parcialmente, sólo con determinadas claves. Por ejemplo:

> SELECT name, meta -> 'country' AS country FROM authors;
      name       | country ------------------+--------- Adam Anderson    | "UK" Barbara Brandini | "CAN" Charles Cooper   | "UK"(3 rows)

El tipo de datos JSONB tiene muchos operadores de uso similar a HStore. Por ejemplo, el siguiente uso del operador ? recupera solo las filas en las que el campo meta contiene la clave de contacto.

> SELECT name,         meta -> 'active' AS active,         meta -> 'contact' AS contact  FROM authors  WHERE meta ? 'contact';
      name       | active |                 contact                         
------------------+--------+-----------------------------------------------
Barbara Brandini | true   | {"email": "barbara@example.com", "phone": "111-222-3333"}
Charles Cooper   | false  | {"email": "charles@example.com"}
(2 rows)

Trabajar con índices

Según la documentación, el tipo de datos HStore "tiene soporte de índices GiST y GIN para los operadores @>, ?, ?& y ?|". Para una explicación detallada de las diferencias entre ambos tipos de índices, consulte aquí. La indexación para JSONB utiliza índices GIN para facilitar la búsqueda eficiente de claves o pares clave-valor.

La sentencia para crear un índice es la que cabría esperar:

> CREATE INDEX idx_hstore ON articles USING GIN(meta);
> CREATE INDEX idx_jsonb ON authors USING GIN(meta);

Estructura SQL con flexibilidad NoSQL

Volvamos al caso de uso original que mencionamos en la introducción. Imaginemos una agencia de contenidos de noticias que almacena sus artículos de forma muy similar a como se haría con un almacén de documentos NoSQL. Tal vez el artículo pueda representarse en JSON como una matriz ordenada de objetos que representan secciones, cada una con contenido de texto, anotaciones y formato. Además, a cada artículo se asocia una serie de metadatos, y esos atributos de metadatos son incoherentes de un artículo a otro.

La descripción anterior encapsula la mayor parte de las necesidades NoSQL de la organización, pero todo lo demás sobre cómo gestiona y organiza sus datos se alinea estrechamente con un modelo de datos relacional.

Al combinar las capacidades NoSQL de un tipo de datos como JSONB con las fortalezas SQL tradicionales de PostgreSQL, la organización puede disfrutar de esquemas flexibles y consultas rápidas en datos anidados sin dejar de ser capaz de realizar operaciones conjuntas y reforzar las relaciones de datos. Los tipos de datos HStore y JSONB de PostgreSQL ofrecen poderosas opciones a los desarrolladores que necesitan la estructura de una base de datos relacional pero también requieren almacenamiento de datos estilo NoSQL.

PostgreSQL a escala

¿Desea almacenar y consultar datos al estilo NoSQL sin salirse del marco de una base de datos relacional tradicional? Tal vez su organización trate los documentos de forma similar a la que hemos descrito en esta entrada. O tal vez esté buscando opciones para gestionar el almacenamiento de datos no estructurados para un gran modelo de lenguaje (LLM) o algún otro proyecto de IA/ML.

El Cluster PostgreSQL en Linode Marketplace le da el modelo relacional y la estructura de una base de datos SQL junto con la escalabilidad horizontal de una base de datos NoSQL. Combine esto con el uso de tipos de datos HStore o JSONB, y tendrá una solución híbrida ideal para aprovechar las capacidades NoSQL mientras trabaja con PostgreSQL.


Comentarios

Dejar una respuesta

Su dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *.