DuckDB o SQLite: la consulta analítica decide antes que el archivo

|Autor: Equipo editorial de QUASA|6 lectura mínima| 1
DuckDB o SQLite: la consulta analítica decide antes que el archivo

SQLite suele ser la elección para una aplicación que inserta, actualiza y busca registros concretos. DuckDB encaja mejor cuando el trabajo principal consiste en agregar muchas filas, calcular ventanas o combinar conjuntos amplios. Ambos pueden guardar datos en un archivo, pero ese rasgo compartido dice poco sobre el tiempo que tardará una consulta.

Si la misma aplicación necesita transacciones e informes, la elección depende también de quién escribe los datos y de cómo se ejecuta el análisis. Una tabla grande no exige por sí sola una migración: una búsqueda selectiva con un índice adecuado plantea un problema distinto de un informe que recorre gran parte de esa tabla.

Por qué cambia el rendimiento según la lectura

La descripción técnica de DuckDB sitúa las consultas analíticas en el centro de su diseño: su ejecución columnar y vectorizada procesa lotes de valores, y el motor puede repartir trabajo entre núcleos. Es una combinación apropiada para sumar importes de muchas filas, agrupar resultados o ejecutar uniones amplias. DuckDB también ofrece transacciones e índices secundarios; su especialización analítica no significa que solo acepte informes.

SQLite almacena habitualmente el contenido de cada registro junto a su identificador de fila. Ese diseño resulta cómodo cuando una consulta necesita recuperar o modificar un registro completo. Para calcular un agregado a partir de unas pocas columnas de muchas filas, en cambio, el motor puede tener que examinar datos que la operación no devuelve. La diferencia efectiva depende de los filtros, los índices y el plan elegido, además del formato de almacenamiento.

Una función de ventana tampoco convierte automáticamente una consulta en una carga pesada: importa cuántas filas ordena o agrupa y con qué frecuencia se ejecuta. La distinción útil es entre llegar a pocos registros y procesar una porción amplia del conjunto. Esa distinción describe mejor el trabajo que un umbral fijo de tamaño.

Mapa de cargas y árbol de decisión

Un índice de SQLite conduce a un registro concreto sin recorrer todos los pedidos.

Para decidir qué motor debe recibir cada operación, conviene clasificar las consultas que la aplicación ejecuta de forma habitual:

  • Claves, filtros selectivos y cambios de pocas filas: SQLite es el punto de partida cuando la aplicación recupera registros concretos y los modifica mediante transacciones breves.
  • Agregaciones, ventanas y uniones amplias: DuckDB merece atención cuando la consulta resume muchas filas o repite cálculos sobre grandes partes de los datos.
  • Búsquedas con ordenación: un índice de SQLite puede ayudar tanto a localizar filas como a entregarlas en el orden solicitado; el resultado depende de las columnas y condiciones de la consulta.
  • Escrituras e informes sobre los mismos datos: se puede mantener la escritura transaccional en SQLite y evaluar DuckDB para el análisis, sin trasladar de entrada todas las operaciones.

La documentación del planificador de SQLite explica que una búsqueda por clave o por índice evita recorrer toda la tabla y que un índice de cobertura puede contener tanto las columnas del filtro como las del resultado. Por eso una consulta que devuelve pocas filas puede seguir siendo rápida en una tabla grande. Antes de atribuir una demora al motor, interesa distinguir si el plan localiza registros mediante un índice o examina la tabla completa.

Los índices tienen un límite práctico en este análisis: favorecen determinadas condiciones y órdenes de lectura, mientras que un informe puede pedir otras agrupaciones y recorrer casi todos los registros de todos modos. También ocupan espacio y deben actualizarse cuando cambian los datos. Si los informes dominan el trabajo, multiplicar índices no reproduce la forma en que DuckDB procesa grandes conjuntos.

Qué demuestra el benchmark de un millón de filas

El benchmark de agrupación por categoría muestra tiempos distintos para DuckDB y SQLite en pedidos sintéticos.

El ensayo publicado por DuckDB Lab presenta diez consultas sobre un millón de pedidos sintéticos, con DuckDB 1.5.2 y SQLite 3.45.1 en un equipo de cuatro CPU virtuales y 8 GB de RAM; para una agrupación por categoría informa 0,020 segundos frente a 2,275 segundos, respectivamente. Es una diferencia medida para esa consulta y esa configuración, no una promesa de rendimiento para cualquier aplicación.

La ruta de lectura del ensayo requiere una salvedad concreta. Su explicación metodológica dice que DuckDB consulta el CSV directamente, pero el SQL mostrado crea primero una tabla de DuckDB a partir de ese CSV y luego consulta la tabla. Por ello no queda claro si los tiempos corresponden a leer el archivo original o a leer datos ya cargados en el almacenamiento del motor. La prueba tampoco mide búsquedas puntuales ni escrituras concurrentes.

Ese contexto importa al comparar resultados propios. Una consulta que agrupa todos los pedidos no representa la latencia de abrir una ficha por identificador; importar los datos tampoco tiene el mismo coste que consultarlos después de la carga. El benchmark ilustra la ventaja posible de DuckDB en agregaciones, pero la decisión de cambiar el archivo principal exige incluir las consultas frecuentes, la preparación de los datos y las escrituras de la aplicación.

La concurrencia cambia la elección

Las reglas de concurrencia de DuckDB permiten que varios hilos de un mismo proceso escriban en la base nativa si sus cambios no entran en conflicto. El acceso de varios procesos al mismo archivo funciona para lectura cuando ninguno escribe; la escritura desde procesos independientes no se coordina automáticamente en ese modelo. Si una aplicación reparte sus transacciones entre procesos, esta restricción puede pesar más que la velocidad de un informe aislado.

La distinción entre hilos y procesos evita una conclusión demasiado amplia sobre DuckDB. Incluso dentro de un proceso, dos transacciones que intentan modificar la misma fila pueden entrar en conflicto. Por su parte, organizar todas las escrituras a través de un único proceso es una opción arquitectónica, pero añade una responsabilidad que debe evaluarse junto al rendimiento analítico.

Compartir datos sin migrar la base transaccional

La extensión SQLite de DuckDB permite adjuntar un archivo SQLite y consultar directamente sus tablas; también permite copiar datos a tablas de DuckDB. En el archivo SQLite, los bloqueos siguen a cargo de SQLite: pueden acceder lectores desde distintos procesos, mientras solo un proceso o hilo escribe a la vez. Esta vía permite conservar las transacciones existentes y añadir consultas analíticas sin sustituir inmediatamente la base de la aplicación.

Consultar las tablas adjuntas y copiarlas al almacenamiento nativo son decisiones distintas. La consulta directa evita mantener otra copia, pero lee los datos desde SQLite en el momento de ejecutar la operación; una copia permite evaluar el almacenamiento de DuckDB y obliga a decidir cuándo actualizarla. En una aplicación hipotética de pedidos con informes periódicos, esa diferencia determina si el informe debe reflejar cambios recientes o puede trabajar con datos preparados con anterioridad.

Así, la elección final puede tener dos motores y un solo origen de escrituras. SQLite puede seguir atendiendo las operaciones puntuales de la aplicación, mientras DuckDB ejecuta el análisis sobre el archivo adjunto o sobre una copia cuando su coste de preparación compense. Si las consultas analíticas pasan a ser la carga principal y las escrituras caben en el modelo de concurrencia elegido, entonces cobra sentido valorar DuckDB como almacenamiento principal.

Lee también:

Compartir:

Suscríbete a nuestro boletín

Reciba las últimas noticias sobre Web3, IA y criptomonedas directamente en su bandeja de entrada.

0