En PostgreSQL muchos desarrolladores se encuentran con la duda: ¿qué estructura de datos usar para guardar información? ¿Usar arrays (ARRAY) para estructuras de datos más simples? ¿O columnas de texto (TEXT) para cadenas? ¿O quizás HSTORE para guardar pares "clave-valor"? Y claro, surge la pregunta: ¿cuándo es mejor JSON o JSONB?
Para ayudarte a aclarar esto, vamos a hablar de las ventajas y desventajas de cada enfoque, y también veremos ejemplos de uso.
¿Cuándo usar arrays (ARRAY) y cuándo JSONB?
Arrays (ARRAY) van genial para datos que son conjuntos homogéneos de valores. Por ejemplo, si tienes una lista de notas de estudiantes o etiquetas para un registro, los arrays son perfectos.
Ejemplo de array:
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name TEXT,
grades INTEGER[] -- array de notas
);
INSERT INTO students (name, grades)
VALUES ('Alicia', ARRAY[90, 85, 88]),
('Beto', ARRAY[70, 75, 78]);
Por otro lado, JSONB es ideal para estructuras más complejas y anidadas. Si quieres guardar datos extra para cada registro, como una descripción para cada nota, JSONB es lo tuyo.
Ejemplo de JSONB:
CREATE TABLE students_json (
id SERIAL PRIMARY KEY,
name TEXT,
grades JSONB -- objeto con datos de notas
);
INSERT INTO students_json (name, grades)
VALUES ('Alicia', '{"Matemáticas": 90, "Ciencias": 85, "Inglés": 88}'),
('Beto', '{"Matemáticas": 70, "Ciencias": 75, "Inglés": 78}');
Diferencias principales
| Criterio | Arrays (ARRAY) |
JSONB |
|---|---|---|
| Estructura | Datos homogéneos de un solo tipo | Estructuras de datos complejas y anidadas |
| Acceso a datos | Por índice: grades[1] |
Por clave: grades->'Matemáticas' |
| Soporte de índices | Solo GIN o BTREE para el array completo |
Índices GIN y BTREE cómodos por claves |
| Cuándo usar | Listas simples de datos (etiquetas, notas, identificadores) | Objetos complejos con claves y valores |
Ejemplos de conversión de array a JSONB y viceversa
Vamos a ver cómo se pueden convertir datos entre arrays y JSONB:
Array → JSONB
SELECT to_jsonb(grades) AS grades_jsonb
FROM students;
-- Resultado:
-- [{"90","85","88"}]
JSONB → Array
SELECT array_agg(value::INTEGER) AS grades_array
FROM jsonb_array_elements_text('["90", "85", "88"]');
-- Resultado:
-- {90,85,88}
Comparación de JSONB y datos de texto (TEXT)
Las columnas de texto son ideales si solo necesitas guardar cadenas de texto o datos no estructurados pequeños. Si tu tarea es buscar coincidencias de texto, por ejemplo, en el nombre de un producto o una descripción, TEXT es tu opción.
CREATE TABLE books (
id SERIAL PRIMARY KEY,
title TEXT,
description TEXT
);
INSERT INTO books (title, description)
VALUES ('SQL Básico', 'Una introducción concisa a SQL'),
('PostgreSQL Avanzado', 'Una guía profunda sobre el rendimiento de PostgreSQL');
¿Cuándo es mejor usar JSONB?
Si tu cadena se convierte en información con estructura anidada (por ejemplo, una descripción con categoría anidada y lista de etiquetas), mejor elige JSONB.
CREATE TABLE books_json (
id SERIAL PRIMARY KEY,
info JSONB
);
INSERT INTO books_json (info)
VALUES ('{"title": "SQL Básico", "tags": ["principiante", "base de datos"]}'),
('{"title": "PostgreSQL Avanzado", "tags": ["rendimiento", "optimización"]}');
Diferencias principales
| Criterio | Texto (TEXT) |
JSONB |
|---|---|---|
| Estructura | Datos no estructurados | Datos estructurados y anidados |
| Búsqueda | Búsqueda de texto completo | Búsqueda por claves, valores, estructura anidada |
| Modificación de datos | Solo reemplazo completo | Modificar claves individuales |
| Cuándo usar | Cadenas de texto simples | Datos complejos en formato clave-valor |
Comparación de JSONB y HSTORE
HSTORE es como el hermano mayor de JSONB, que permite guardar pares "clave-valor". Por ejemplo, si tu estructura de datos es simple (no necesita anidamiento ni arrays), HSTORE será más ligero y rápido.
CREATE TABLE products (
id SERIAL PRIMARY KEY,
attributes HSTORE
);
INSERT INTO products (attributes)
VALUES ('"color"=>"rojo", "talla"=>"M"'),
('"color"=>"azul", "talla"=>"L"');
¿Por qué JSONB reemplazó a HSTORE?
Aunque HSTORE es cómodo para pares "clave-valor", no soporta anidamiento ni arrays, lo que hace que JSONB sea más versátil. Si tus objetos ya no son simples, JSONB es el siguiente paso natural.
Diferencias principales
| Criterio | HSTORE | JSONB |
|---|---|---|
| Estructura | Pares "clave-valor", sin anidamiento | Estructuras anidadas completas |
| Soporte de arrays | No | Sí |
| Búsqueda | Solo por clave | Por claves, valores, estructura anidada |
| Cuándo usar | Pares clave-valor simples | Estructuras de datos complejas |
¿Cómo elegir el tipo de dato adecuado?
Si tienes:
- Estructura simple — listas o datos homogéneos, usa arrays (
ARRAY). - Cadenas simples o descripciones, usa columnas de texto (
TEXT). - Pares "clave-valor" sin anidamiento, elige
HSTORE. - Objetos anidados y arrays, estructura de datos compleja — necesitas JSONB.
Ejemplos de conversión entre formatos
TEXT → JSONB
SELECT to_jsonb('Ejemplo de texto simple') AS jsonb_form;
-- Resultado: "Ejemplo de texto simple"
JSONB → TEXT
SELECT info::TEXT AS text_form
FROM books_json;
-- Resultado: {"title": "SQL Básico", "tags": ["principiante", "base de datos"]}
HSTORE → JSONB
SELECT hstore_to_jsonb(attributes) AS jsonb_form
FROM products;
-- Resultado: {"color": "rojo", "talla": "M"}
JSONB → HSTORE
SELECT jsonb_to_hstore('{"color": "rojo", "talla": "M"}') AS hstore_form;
-- Resultado: "color"=>"rojo", "talla"=>"M"
¿En qué fijarse?
Si necesitas máxima flexibilidad y soporte para estructuras complejas, elige JSONB. Pero si tu tarea son estructuras de datos simples, como arrays, texto o pares "clave-valor", usa los tipos de datos correspondientes (ARRAY, TEXT, HSTORE).
No olvides que elegir bien la estructura de datos te ahorrará dolores de cabeza más adelante y mejorará el rendimiento de tus consultas.
GO TO FULL VERSION