27 puntos por GN⁺ 2025-12-03 | 2 comentarios | Compartir por WhatsApp
  • Se demostró experimentalmente que la estructura de escritor único y la naturaleza embebida de SQLite pueden, de hecho, mejorar la escalabilidad y el rendimiento
  • En las mismas condiciones, Postgres cayó hasta 348 TPS con latencia de red, mientras que SQLite, al eliminar la red, alcanzó 44,096 TPS
  • Aprovechando el modelo de escritor único con procesamiento por lotes y transacciones granulares basadas en SAVEPOINT, registró hasta 186,157 TPS y 102,545 TPS en una configuración estable
  • La ley de Amdahl explica el cuello de botella de las bases de datos basadas en red, y SQLite mantiene una alta eficiencia al evitarlo
  • Estos resultados destacan la viabilidad de usar SQLite en entornos locales y la importancia de eliminar los cuellos de botella de red

Estructura de SQLite y entorno del experimento

  • SQLite no tiene MVCC y solo permite un escritor, pero esta estructura, de hecho, hace posible una alta escalabilidad
    • Como base de datos embebida, no tiene sobrecarga de red
  • El benchmark se realizó en una MacBook Pro (2021) con Apple M1 Pro y 16 GB de memoria
  • El experimento no buscó una optimización perfecta, sino mostrar que es posible lograr un alto rendimiento de escritura incluso en condiciones comunes

Definición de TPS y ejemplo de transacción

  • TPS no significa simplemente velocidad de escritura, sino transacciones interactivas (Interactive Transaction)
    • Ejemplo: en una transferencia entre cuentas, varias consultas y código de aplicación se ejecutan dentro de una sola transacción
  • Las transacciones pueden revertir el estado cuando ocurre un error, por lo que cumplen un papel clave para mantener la consistencia

Configuración del benchmark

  • Se usaron virtual threads basados en Clojure para simular solicitudes concurrentes a gran escala
  • Postgres se configuró con un pool de conexiones basado en HikariCP, mientras que SQLite usó un solo escritor y tantas conexiones de lectura como núcleos
  • Ambas bases de datos utilizaron una tabla account simple con los campos id, balance, e insertaron mil millones de filas
  • La actividad de los usuarios sigue una distribución de ley de potencia (0.9995), con aproximadamente 100 mil usuarios activos

Rendimiento de la base de datos en red (Postgres)

  • En el mismo servidor, Postgres alcanzó 13,756 TPS
  • Al agregar 5 ms de latencia de red, cayó a 1,214 TPS, y con 10 ms a 702 TPS
  • Tras aplicar aislamiento serializable, bajó a 660 TPS, y con consultas adicionales descendió a 348 TPS
  • Esto muestra, de acuerdo con la ley de Amdahl, que el cuello de botella de red limita el rendimiento total
    • Cuando aumenta la latencia de red, la contención de locks de transacción se intensifica y deja de escalar

Ventajas embebidas de SQLite

  • Al eliminar la red, SQLite alcanzó 44,096 TPS
    • Al desaparecer el cuello de botella de red, se minimiza el impacto de la ley de Amdahl
  • Al aplicar procesamiento por lotes (batch processing) aprovechando su estructura de escritor único, subió hasta 186,157 TPS
    • El ajuste dinámico del tamaño del lote optimiza automáticamente la latencia (latency) y el rendimiento (throughput)

Transacciones granulares mediante SAVEPOINT

  • Para evitar que falle una transacción individual dentro de un lote, se aplicaron transacciones anidadas con SAVEPOINT
    • Si ocurre un fallo, solo se revierte esa transacción y se mantiene el lote completo
  • Incluso con este enfoque, se mantuvieron 121,922 TPS

Prueba de carga mixta de lectura/escritura

  • El 75% de las solicitudes fueron lecturas y el 25% escrituras
  • Se utilizó un pool de hilos de lectura separado para aislar las solicitudes de lectura y evitar que interfieran con las escrituras
  • Como resultado, se alcanzaron 102,545 TPS

Resumen comparativo de rendimiento

Condición Postgres SQLite
Sin red 13,756 44,096
5 ms de latencia 1,214 n/a
10 ms de latencia 702 n/a
10 ms + serializable 660 n/a
Procesamiento por lotes n/a 186,157
Lotes + SAVEPOINT n/a 121,922
Lotes + SAVEPOINT + lecturas n/a 102,545

Conclusión

  • SQLite logra TPS mucho más altos que las bases de datos basadas en red gracias a su modelo de escritor único y estructura embebida
  • Maximiza la eficiencia al evitar los límites de cuello de botella de red que plantea la ley de Amdahl
  • Todo el código está publicado en GitHub, y junto con ello se presentan materiales relacionados sobre la ley de Amdahl, ley de potencia y casos de escalado de SQLite
  • SQLite es una opción muy efectiva para procesamiento de transacciones de alto rendimiento en entornos locales

2 comentarios

 
ppp123 2025-12-10

Entonces, si se va a usar solo en un entorno local sin recurrir a un servidor externo, la idea es que no hace falta pagar el impuesto de la red, ¿no? (VFS vs Socket)

 
GN⁺ 2025-12-03
Opiniones en Hacker News
  • Estoy construyendo un servidor ORM/CRUD híbrido basado en protobuf sobre SQLite
    El código y la explicación están en GitHub - accretional/collector
    Permite 5–15 ms de downtime durante respaldos en tiempo real, encolar cientos de solicitudes de lectura/escritura, latencia total de CRUD de alrededor de 1 ms, e incluso respaldo en streaming basado en WAL
    Antes solo usaba Postgres y Spanner, pero si a Collector le agregan particionado, creo que no volvería a usar Postgres

    • Me pregunto si consideraste hacer respaldos sin downtime con SQLite + WAL usando un sistema de archivos con snapshots atómicos como BTRFS. Tomas el snapshot, haces el respaldo con calma y luego lo eliminas
  • La desventaja es que todos los datos y operaciones tienen que caber en una sola máquina
    Si usas una instancia u-24tb1.112xlarge de AWS (448 vcore, 24 TB de RAM, 64 TB de EBS), tienes bastante margen

    • Pero si rentas un servidor bare metal de Hetzner, el rendimiento por núcleo es 2–3 veces mayor y el costo se reduce en 90%
    • La talla máxima teórica de la base de datos en SQLite es de 281 TB, según indica la documentación oficial. En la práctica, el límite del sistema de archivos es menor, pero funciona bien
    • Escalar verticalmente en una sola máquina es confiable, pero tiene poca elasticidad. Si el tráfico se dispara, tienes que sobreaprovisionar o aceptar fallas
    • Viendo el enlace yourdatafitsinram.net, que pregunta “¿tus datos caben en RAM?”, creo que para un nodo único de alto rendimiento un servidor dedicado sale mejor que EC2
  • El artículo enfatiza la eficiencia de SQLite, pero siento que no queda claro contra qué se está comparando
    Eso pasa porque parte de una arquitectura con servidores separados y luego mide el rendimiento de una BD embebida local
    En las mismas condiciones, un Postgres local bien afinado también podría lograr un rendimiento parecido

    • SQLite es más rápido incluso que Postgres en la misma máquina. Tiene sentido probarlo según la configuración real de despliegue
    • También puedes poner SQLite detrás de un request handler y correrlo desde otro servidor. Al final, una BD no es más que la combinación de un procesador de solicitudes y almacenamiento
    • En una sola máquina, lo importante es el raw throughput. SQLite es 10 veces más rápido que PG, y PG se vuelve más lento mientras más complejas sean las transacciones
    • Decir “entonces SQLite no es un punto de comparación válido” es simplificar demasiado. El artículo quedaría demasiado corto
    • SQLite no sirve solo para móvil o embebidos; también encaja bien en apps de servidor con baja concurrencia. No es una BD solo para servidores web
  • Limitar Postgres a 8 conexiones podría ser el cuello de botella
    Estaría bien publicar también el uso de CPU e hilos, y volver a probar con un pool de conexiones más grande

    • Ajustar el pool al número de núcleos (8) está bien, pero si hay un sleep dentro de la transacción, se crea un cuello de botella
      Si lo subes a 64 conexiones, el throughput podría aumentar 8 veces. Hay que escalar la configuración del cliente hasta llegar al límite
    • Me cuesta creer las cifras de este artículo. Yo consigo TPS mucho más altos incluso con MySQL sobre red
  • La clave es reconocer cuándo la latencia de red es el cuello de botella
    En muchas cargas de trabajo, una BD local común supera a una BD remota excelente
    Lo importante no es “qué BD es mejor”, sino “si realmente necesitas cruzar el límite de la red

    • (Autor) Exacto. No quería entrar en el debate SQLite vs Postgres, sino hablar de las limitaciones de las BD basadas en red
    • Claro, si pones todo en memoria y usas Redis o Memcache, el rendimiento sube fácilmente. Pero ahí ya cambian las reglas
  • Las BD en red tienen la ventaja de facilitar el redespliegue de la app
    Puedes levantar una instancia nueva y apagar la anterior, logrando un despliegue casi sin downtime
    Si SQLite está en la misma instancia, al reemplazarla tienes que volver a levantar la BD, así que se vuelve más complejo. Me pregunto si han sufrido este tipo de problema en producción

    • Para usar SQLite en producción necesitas almacenamiento persistente y NVMe. Normalmente se opera en un solo servidor bare metal
      Durante una migración puede haber downtime. Gracias a Litestream, ahora la replicación y los respaldos son mucho más fáciles
    • SQLite soporta acceso multiproceso, así que también puedes hacer reemplazos sin downtime levantando un proceso nuevo y apagando el anterior
  • El autor configuró PRAGMA synchronous="normal", lo que significa que no hace fsync en cada operación
    Para una comparación justa debería usar "full"

    • Pero en modo WAL, "normal" también está bien. Si se corta la energía, se pierde durabilidad, pero la consistencia de la transacción se mantiene
  • Me pregunto cómo sería una configuración de HA (alta disponibilidad) con SQLite
    Como mínimo debería poder hacerse failover automático

    • SQLite es una biblioteca en C, así que se puede extender con proyectos como rqlite, litestream y litefs
      Ahora mismo estoy dudando entre Postgres y SQLite (incluyendo litestream).
      Mi app tolera algo de downtime, así que escalar verticalmente en una sola máquina me resulta más simple y barato
    • Hace poco revivió un proyecto multimaestro llamado Marmot después de dos años.
      En Marmot GitHub acaban de agregar un mecanismo de replicación basado en gossip
  • Me pregunto si hay casos reales de SQLite llevado al límite en producción

  • Me gustaría saber más o menos cuál es el límite de usuarios para SQLite vs Postgres en una webapp o entorno de e-commerce típico
    Con las actualizaciones recientes, SQLite permite lecturas concurrentes pero sigue aceptando una sola escritura
    Quisiera saber en qué casos eso se vuelve un problema y si, pensando en escalar, conviene más empezar directamente con Postgres