Saltar al contenido

010 — El mapa de los motores: seis familias y un criterio

🗂️ parte 🎚️ nivel ⏱️ duración 📗 clase

Programa · Parte 00 · ← Anterior · Siguiente →

Parte 00 — Primeros pasos: del archivo a la base de datos · Fundamentos · 2 horas estimadas · motores postgresql, mongodb, redis, cassandra, neo4j, duckdb, opensearch, qdrant · laboratorio labs/02-polyglot-modeling · 3 fuentes.

Conceptos centrales: familias de motores · modelo de agregado · patrón de acceso · multimodelo

En este caso se comparan 9 motores: 8 lo resuelven (0 con el resultado comprobado por máquina) y 1 no, con el motivo escrito.

De qué trata esta clase

El mapa que se usará durante todo el programa: seis familias de motores, qué patrón de acceso optimiza cada una y qué paga a cambio. Cierra la rampa de entrada con un criterio de elección en lugar de una lista de nombres de producto.

flowchart LR
    C["🗄️ Clase 010"]
    C --> K1["familias de motores"]
    C --> K2["modelo de agregado"]
    C --> K3["patrón de acceso"]
    C --> K4["multimodelo"]
    classDef raiz fill:#0b3d2e,stroke:#3fb950,color:#fff
    class C raiz

Antes de empezar

Esta clase supone que ya trabajaste lo siguiente. Si algo de la última columna no te suena, vuelve a esa clase antes de seguir: aquí se usa sin volver a explicarlo.

# Clase previa Lo que se da por sabido
009 Cuándo NO necesitas una base de datos criterio de decisión · motor embebido · costo de operación · alternativas

Vocabulario de la clase

Los términos que siguen se usan más adelante con este significado exacto. La definición completa, con sus términos relacionados, está en el glosario del programa.

Término Qué significa Procedencia
familias de motores Las formas de organizar datos que estructuran este programa: relacional, documental, clave-valor, grafo, columnas anchas y series temporales, más los índices de búsqueda y los vectoriales como casos especializados. Cada familia optimiza un patrón de acceso y paga en los demás. se introduce aquí
modelo de agregado Cómo agrupa el motor los datos que lee y escribe de una vez. El relacional trabaja con filas que se recomponen por reunión; los motores de agregado guardan la unidad completa junta y evitan la reunión, a cambio de duplicar. se introduce aquí
patrón de acceso La lista concreta de consultas y escrituras que el sistema tendrá que servir, con su frecuencia y su latencia aceptable. Es el dato de entrada del diseño: sin él, elegir modelo o índice es adivinar. se introduce aquí
multimodelo Motor que soporta varias familias a la vez —PostgreSQL con JSONB, vectores y búsqueda de texto—. Reduce el número de sistemas que hay que operar; el riesgo es dar por hecho que hacer varias cosas equivale a hacerlas todas bien. se introduce aquí

Propósito

Poner orden en los nombres. Antes de estudiar cada familia de motores conviene tener el mapa completo: cuántas hay, qué problema resolvió cada una y en qué se parecen más de lo que su publicidad sugiere.

Resultados de aprendizaje

Al terminar podrás:

  1. Nombrar las seis familias principales y el problema que resuelve cada una.
  2. Situar en el mapa los motores que aparecen en cualquier oferta de trabajo.
  3. Explicar por qué «SQL frente a NoSQL» es una división pobre.
  4. Elegir familia a partir del patrón de acceso, no del nombre del producto.
  5. Nombrar la fuente de cada afirmación anterior.

Fundamentos

Seis familias y un criterio

Lo que separa a las familias no es la sintaxis: es qué unidad de datos manejan y qué acceso optimizan.

Familia Unidad Optimiza Ejemplos
Relacional La fila, en tablas relacionadas Consultas variadas con integridad PostgreSQL, MySQL, SQL Server, Oracle, SQLite
Documental El documento (un agregado completo) Leer y escribir el agregado entero MongoDB, CouchDB
Clave-valor El par clave-valor Acceso por clave, latencia mínima Redis, DynamoDB
Columnas anchas La partición, ordenada por clave Escritura masiva y lectura por partición Cassandra, ScyllaDB
Grafo El nodo y la arista Recorrer relaciones de profundidad variable Neo4j
Columnar / analítico La columna Agregar sobre muchísimas filas DuckDB, ClickHouse, BigQuery

A esas seis se añaden dos especializados que hoy aparecen en casi todo sistema: búsqueda de texto (OpenSearch, Elasticsearch) y vectorial (Qdrant, pgvector, Milvus), que resuelven «encontrar lo que se parece» en dos sentidos distintos de parecerse.

Por qué «SQL frente a NoSQL» dice poco

La división es histórica —el término «NoSQL» nació como etiqueta de un encuentro en 2009— y agrupa cosas que no se parecen en nada: MongoDB y Redis y Cassandra y Neo4j están en el mismo saco, y sus modelos de datos son tan distintos entre sí como cualquiera de ellos lo es de PostgreSQL. Además, casi todos han acabado añadiendo un lenguaje de consulta declarativo, así que ni siquiera la parte del «no SQL» describe bien la realidad.

Sadalage y Fowler proponen una división mejor en NoSQL Distilled: agregado frente a relacional. Los modelos de agregado —documental, clave-valor, columnas anchas— tratan un grupo de datos como una unidad indivisible de lectura, escritura y consistencia. El relacional y el de grafos no: descomponen y relacionan.

Esa distinción sí predice el comportamiento: dónde hay transacciones, qué es atómico, qué consultas son baratas y cuáles imposibles.

La pregunta que sí elige familia

No es «¿qué motor uso?», es «¿cómo se van a acceder estos datos?»:

Multimodelo: la frontera se ha borrado

Conviene añadir un matiz que el mapa por sí solo no da: hoy casi todos los motores hacen un poco de todo. PostgreSQL guarda JSON con índices, hace búsqueda de texto y —con pgvector— búsqueda vectorial. MongoDB tiene transacciones de varios documentos. Redis tiene estructuras de datos, no solo pares.

La consecuencia práctica es importante: la respuesta correcta suele ser un solo motor generalista, y añadir un segundo tiene que justificarse con una medición, no con una categoría. Esa es la tesis que cierra el programa.

flowchart TD
    A["¿Cómo se accede<br/>a estos datos?"] --> B{"¿Siempre el mismo<br/>bloque entero?"}
    B -- "Sí" --> C{"¿Por clave y<br/>con latencia mínima?"}
    C -- "Sí" --> KV["Clave-valor"]
    C -- "No" --> DOC["Documental"]
    B -- "No" --> D{"¿La pregunta es<br/>sobre caminos?"}
    D -- "Sí" --> G["Grafo"]
    D -- "No" --> E{"¿Agregar millones<br/>de filas?"}
    E -- "Sí" --> COL["Columnar"]
    E -- "No" --> R["Relacional"]

Ejemplo trabajado

Una plataforma educativa, y sus cinco necesidades reales:

Necesidad Patrón de acceso Familia
Inscripciones y pagos Muchas relaciones, reglas que no se pueden romper Relacional
Sesiones de usuario Por clave, muy frecuente, desechable Clave-valor
Buscar en el catálogo Texto con relevancia y errores tipográficos Búsqueda
Panel de dirección Agregar todo el histórico Columnar
«Cursos parecidos a este» Similitud semántica Vectorial

La respuesta ingenua es cinco motores. La respuesta buena empieza por comprobar cuántas de las cinco cubre uno solo: PostgreSQL resuelve la primera de forma nativa, la tercera con tsvector, la cuarta con vistas materializadas mientras el volumen sea moderado y la quinta con pgvector. Quedaría solo la segunda, y ahí Redis se justifica por sí solo porque el dato es desechable por naturaleza.

De cinco motores a dos, y cada uno de los que no entró ahorra un plan de respaldo, un panel de vigilancia y una coherencia que mantener. Cuando alguna de las cuatro deje de rendir —y se sabrá porque se mide— habrá evidencia para añadir el motor que corresponda. Ese orden, evidencia antes que adopción, es el que defiende la última parte de este programa.

Errores frecuentes

  1. Elegir por popularidad. Un ranking mide menciones y ofertas de trabajo, no ajuste a un problema.
  2. Creer que «NoSQL» es una categoría técnica. Agrupa cuatro modelos que no se parecen.
  3. Elegir por el lenguaje de consulta. La sintaxis se aprende en una semana; el modelo de datos condiciona el sistema durante años.
  4. Añadir un motor por una funcionalidad y no por una carga. «Tiene búsqueda vectorial» no es una necesidad.
  5. Suponer que un motor especializado siempre gana. Gana en su terreno, y pierde en todo lo demás; el sistema tiene que atravesar los dos.
  6. Ignorar que el motor que ya está puede hacerlo. Es la comprobación más barata y la que menos se hace.

Ejemplo de transferencia

Este mapa es el índice del resto del programa: cada familia tiene su parte, con su modelo, sus consultas, sus límites y su caso ejecutado en varios motores. Y cada clase, a partir de aquí, resuelve el mismo problema en varios de ellos y escribe por qué sí y por qué no conviene resolverlo en cada uno. La decisión de familia no se toma una vez: se revisa con evidencia cada vez que aparece una carga nueva.

Reto de transferencia

  1. Elige un sistema que uses o conozcas y enumera sus tres o cuatro cargas de datos distintas.
  2. Sitúa cada una en una familia, justificando con el patrón de acceso.
  3. Comprueba cuántas de esas cargas cubriría un solo motor generalista.
  4. Para la carga que no cubra, escribe qué medición demostraría que hace falta otro motor.

Preguntas de evaluación

  1. Nombra las seis familias y el problema que resuelve cada una.
  2. ¿Por qué la división «SQL frente a NoSQL» explica poco? Propón una mejor.
  3. Da un caso en el que un motor documental es peor opción que uno relacional, y otro en el que sea mejor.
  4. ¿Qué comprobación conviene hacer antes de añadir un motor especializado a una arquitectura?

🌐 El mismo problema en cada motor

Caso: Seis familias, y la pregunta que decide cuál corresponde

Lo que separa a las familias de motores no es la sintaxis: es qué unidad de datos manejan y qué acceso optimizan. Y la pregunta que elige familia no es «¿qué motor uso?» sino «¿cómo se van a acceder estos datos?».

Esta comparación es el índice del resto del programa: un motor representativo de cada familia, con el patrón de acceso que le corresponde y con el precio que se paga al elegirlo. Cada uno tiene después su propia parte, con su modelo, sus consultas, sus límites y su caso ejecutado.

Y una advertencia que el mapa por sí solo no da: hoy casi todos los motores hacen un poco de todo, así que la respuesta correcta suele ser un solo motor generalista, y añadir un segundo tiene que justificarse con una medición y no con una categoría.

Esta comparación es conceptual: la decisión no se reduce a una consulta con resultado, así que aquí no hay sello de máquina. Lo que se compara es lo que cada motor ofrece y a qué precio, con la página oficial al lado de cada afirmación.

Motor ¿Resuelve el caso? Nivel de prueba Código Fuente
PostgreSQL conceptual doc oficial
MongoDB conceptual doc oficial
Redis conceptual doc oficial
Apache Cassandra conceptual doc oficial
Neo4j conceptual doc oficial
DuckDB conceptual doc oficial
OpenSearch conceptual doc oficial
Qdrant conceptual doc oficial
SQLite no doc oficial

Los que resuelven el caso

PostgreSQL

MongoDB

Redis

Apache Cassandra

Neo4j

DuckDB

OpenSearch

Qdrant

Los que no resuelven este caso — y qué se hace en su lugar

Descartar un motor con un argumento es tan formativo como usarlo. Ninguna de estas filas dice que el motor sea peor: dice que este problema no es el suyo.

Motor Por qué no Qué se hace en su lugar Fuente
SQLite No es una familia distinta: es un motor relacional, y ya está representado por PostgreSQL en este mapa. Lo que lo distingue —que no tenga servidor— es una decisión de despliegue, no un modelo de datos. Se compara donde esa distinción sí importa: en la clase sobre cuándo no hace falta una base de datos con servidor, y en la de motores embebidos. doc

Laboratorio

python scripts/validate_repository.py
# labs/02-polyglot-modeling se entrega escrito: no hay guion que ejecutar

Guarda como evidencia la salida completa, la versión del motor y la semilla o los parámetros usados. Una captura sin comando no es evidencia: no se puede repetir.

Evaluación

Criterio Peso Qué se comprueba
Comprensión conceptual 25 % Explica el mecanismo, no solo el resultado
Ejecución reproducible 25 % Otra persona obtiene lo mismo con las instrucciones dadas
Interpretación basada en evidencia 25 % Cada conclusión se apoya en una salida o una medición
Límites y riesgos declarados 25 % Dice qué no demuestra el ejercicio y qué faltaría en producción

La clase se da por superada cuando la respuesta explica el mecanismo, muestra la salida que la respalda y declara al menos un límite del ejercicio.

Fuentes de esta clase

Todo lo afirmado arriba procede de estas obras. Los identificadores viven en catalog/sources.json y el estado de los enlaces se comprueba con python scripts/check_external_links.py.


Programa · Parte 00 · ← Anterior · Siguiente →