SQLite en el desarrollo móvil: qué es y cómo funciona

Autor: IT Sectr Publicado: 2026-03-11 Tiempo de lectura: 10 min

SQLite es una base de datos relacional embebida que funciona sin un proceso de servidor independiente y almacena toda la base de datos en un solo archivo en el dispositivo. Gracias a la configuración cero, el tamaño reducido de la biblioteca y el soporte completo de SQL, SQLite se ha convertido en el estándar para el almacenamiento local de datos en aplicaciones móviles. Según el SQLite Consortium (2025), este SGBD se utiliza en más de 4 mil millones de dispositivos, incluidos todos los teléfonos inteligentes con iOS y Android.

Puntos clave

  • SQLite es un SGBD relacional embebido con configuración cero y almacenamiento de datos en un solo archivo.
  • Transacciones ACID garantizan la integridad de los datos incluso ante fallos de alimentación o cierres inesperados de la aplicación.
  • Tipificación de datos dinámica: SQLite no requiere especificación estricta del tipo de columna al crear una tabla.
  • Room es una biblioteca ORM para Android que simplifica el trabajo con SQLite mediante DAO y anotaciones.
  • CoreData puede usar SQLite como Persistent Store en iOS, pero añade una capa de gestión de objetos.

¿Qué es SQLite?

SQLite es una biblioteca en lenguaje C que implementa un SGBD relacional sin servidor dedicado. Se integra directamente en la aplicación, leyendo y escribiendo datos en un archivo ordinario del sistema de archivos del dispositivo. El tamaño de la biblioteca es de aproximadamente 600 KB, lo que convierte a SQLite en la base de datos SQL completa más ligera.

SQLite soporta la mayor parte del estándar SQL:1999, incluyendo JOIN, subconsultas, disparadores, vistas, índices y funciones de ventana. Las limitaciones afectan a ALTER TABLE (soporte limitado) y a los RIGHT/FULL OUTER JOIN completos. No obstante, para aplicaciones móviles, la funcionalidad de SQLite es suficiente en el 99% de los casos de almacenamiento local.

Según la encuesta a desarrolladores de Stack Overflow (2025), SQLite es la base de datos más popular para soluciones embebidas y ocupa el tercer lugar en popularidad entre todos los SGBD, después de MySQL y PostgreSQL. En el desarrollo móvil, SQLite se utiliza en cada aplicación, ya sea directamente o a través de envoltorios.

Características clave de SQLite

Configuración cero — SQLite no requiere instalación, configuración de permisos, creación de usuarios ni inicio de servicios. La biblioteca se enlaza al proyecto y la base de datos se crea llamando a una sola función. Esto simplifica radicalmente el despliegue en comparación con los SGBD cliente-servidor, que requieren instalación del servidor, configuración de puertos y creación de usuarios.

El archivo de base de datos SQLite es un archivo multiplataforma ordinario que se puede copiar, analizar, enviar por red o restaurar desde una copia de seguridad. El formato del archivo es estable a nivel de API: los archivos SQLite 3 creados en 2004 se abren con la versión actual de la biblioteca, lo que garantiza la compatibilidad de datos a largo plazo.

Cómo funciona SQLite: arquitectura y almacenamiento

La arquitectura de SQLite consta de ocho máquinas virtuales: Tokenizer, Parser, Code Generator, VM, B-Tree, Pager, OS Interface y Utilities. Una consulta SQL pasa por el Tokenizer (división en tokens), el Parser (construcción de un AST), el Code Generator (conversión a bytecode) y se ejecuta en la máquina virtual, que lee las páginas de datos a través de B-Tree y Pager.

SQLite utiliza B-Tree para almacenar tablas e índices. Cada tabla se almacena como un B-Tree independiente, donde los nodos hoja contienen las filas de datos. Los índices también se almacenan como B-Tree, pero con claves en las hojas. Pager gestiona la carga de páginas (por defecto 4096 bytes) desde el archivo a la memoria, proporcionando transacciones ACID mediante un diario o WAL.

Modos de registro

WAL (Write-Ahead Logging) es el modo recomendado para aplicaciones móviles. Los cambios se escriben primero en un archivo WAL independiente y luego se trasladan periódicamente a la base de datos principal. WAL permite leer (datos antiguos) y escribir (a través de WAL) simultáneamente en la base de datos, lo que mejora el rendimiento de las aplicaciones multihilo. El diario estándar (rollback journal) bloquea la lectura durante la escritura.

ParámetroRollback JournalWAL (Write-Ahead Logging)
Lectura durante escrituraBloqueadaPermitida (lee datos antiguos)
Rendimiento de escrituraMedioAlto (escritura secuencial en WAL)
Consumo de discoMenor (solo diario de reversión)Mayor (WAL + base de datos principal)
Recuperación ante fallosReversión al último punto de controlRecuperación desde WAL (sin pérdida de datos)
RecomendaciónPara escenarios monohiloPara aplicaciones móviles típicas

El cambio entre modos se realiza con una sola consulta SQL: PRAGMA journal_mode=WAL. Para aplicaciones móviles con sincronización en segundo plano y un hilo de UI que lee datos simultáneamente, WAL ofrece un mejor rendimiento y ausencia de bloqueos de interfaz.

SQLite frente a otras bases de datos en el desarrollo móvil

SQLite no es la única opción para el almacenamiento local de datos, pero sí la más versátil. Realm ofrece una mayor velocidad de acceso directo a objetos en memoria, pero utiliza su propio formato NoSQL y tiene un tamaño de biblioteca mayor. Core Data en iOS es una capa ORM sobre SQLite que añade gestión de grafos de objetos y deshacer operaciones.

Para la mayoría de las aplicaciones, SQLite sigue siendo la opción óptima gracias a su rendimiento predecible, ausencia de vendor lock-in y estabilidad probada a lo largo del tiempo. Realm y Core Data se justifican en proyectos con grafos de objetos complejos, consultas reactivas o requisitos de sincronización entre dispositivos.

CaracterísticaSQLiteRealmCore Data
Tipo de base de datosRelacional (SQL)NoSQL (orientada a objetos)ORM (sobre SQLite)
Tamaño de biblioteca~600 KB~4 MBIntegrado en SDK de Apple
RendimientoMedioAlto (objetos en memoria)Medio (sobrecarga ORM)
PlataformasiOS, Android, Web, EscritorioiOS, Android, Node.jsiOS, macOS
Vendor lock-inNinguno (estándar abierto)Medio (formato propio)Alto (solo Apple)

La elección entre SQLite, Realm y Core Data depende de la plataforma, los requisitos del modelo de objetos y la estrategia de sincronización. Para proyectos multiplataforma (KMP, Flutter), SQLite sigue siendo la única opción universal que funciona en todas las plataformas objetivo sin cambios en el modelo de datos.

SQLite en Android: Room y SQLiteOpenHelper

Room es una biblioteca de Android Jetpack que proporciona una capa ORM sobre SQLite. Room genera automáticamente consultas SQL a partir de interfaces DAO anotadas, verifica la corrección de las consultas en tiempo de compilación y admite migraciones de base de datos cuando cambia el esquema. Room es la forma recomendada de trabajar con SQLite en Android.

SQLiteOpenHelper es una API de bajo nivel para la gestión directa de SQLite sin ORM. La clase gestiona la creación, apertura y actualización de la base de datos. SQLiteOpenHelper es adecuado para proyectos con consultas SQL sencillas o cuando se necesita un control total sobre la lógica SQL sin la abstracción de Room.

Ejemplo de entidad y DAO para Room

Una entidad en Room se anota con @Entity, y un DAO con @Dao. Room traduce los métodos anotados en consultas SQL: @Insert genera INSERT, @Query genera SELECT con el SQL especificado. Las migraciones se añaden mediante Migration con las versiones de esquema antigua y nueva especificadas. Room valida el SQL en tiempo de compilación, eliminando errores de sintaxis en producción.

kotlin
@Entity
data class User(
    @PrimaryKey val id: Long,
    val name: String,
    @ColumnInfo(name = "created_at")
    val createdAt: Long
)

@Dao
interface UserDao {
    @Query("SELECT * FROM user ORDER BY name ASC")
    suspend fun getAllUsers(): List<User>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUser(user: User)

    @Query("DELETE FROM user WHERE id = :id")
    suspend fun deleteUser(id: Long)
}

Room genera automáticamente la implementación UserDao_Impl, que contiene consultas SQLite en tiempo de ejecución a través del RoomDatabase interno. Gracias a las corrutinas (suspend), los métodos DAO se ejecutan de forma asíncrona en un hilo en segundo plano sin bloquear la UI. Los tipos de retorno Flow en @Query actualizan automáticamente el resultado cuando la tabla cambia.

SQLite en iOS: FMDB y GRDB

FMDB es un envoltorio en Objective-C sobre la API C de SQLite, históricamente la primera biblioteca popular para iOS. Proporciona objetos FMDatabase y FMResultSet para ejecutar consultas y obtener resultados. FMDB es simple y minimalista, pero no soporta construcciones específicas de Swift: opcionales, Codable, async/await.

GRDB es una biblioteca moderna en Swift para trabajar con SQLite. Proporciona una API type-safe, soporte para Codable, Combine Publishers, async/await, migraciones y observación de cambios en tiempo real. GRDB es preferible para proyectos nuevos en Swift gracias a su completa integración con Swift Concurrency y una mejor legibilidad del código.

Ejemplo de GRDB en Swift

GRDB define tablas mediante clases Record que cumplen los protocolos FetchableRecord y TableRecord. Las consultas se escriben en Swift con sintaxis type-safe en lugar de SQL puro. GRDB también soporta DatabaseMigrator para el versionado de esquemas y migraciones entre versiones de la aplicación.

swift
struct User: Codable, FetchableRecord, TableRecord {
    var id: Int64
    var name: String
    var createdAt: Date
}

let dbPool = try DatabasePool(path: dbPath)
var migrator = DatabaseMigrator()
migrator.registerMigration("v1") { db in
    try db.create(table: "user") { t in
        t.autoIncrementedPrimaryKey("id")
        t.column("name", .text).notNull()
        t.column("createdAt", .datetime).notNull()
    }
}

let users = try await dbPool.read { db in
    try User.order(Column("name")).fetchAll(db)
}

DatabasePool utiliza el modo WAL de SQLite para lectura concurrente. Múltiples lectores pueden acceder a la base de datos simultáneamente mientras un solo escritor actualiza los datos a través de WAL. GRDB gestiona automáticamente las conexiones y transacciones, proporcionando acceso thread-safe a la base de datos desde cualquier hilo sin sincronización manual.

Optimización del rendimiento de SQLite

Los índices son la forma más eficaz de acelerar las consultas SQLite. Se crea un índice en las columnas utilizadas en las cláusulas WHERE, JOIN y ORDER BY. Para una tabla con 100000 registros, la búsqueda por una columna indexada toma milisegundos en lugar de segundos. Sin embargo, los índices ralentizan las operaciones INSERT y UPDATE, por lo que su número debe equilibrarse con la frecuencia de escritura.

La inserción por lotes (batch insert) dentro de una sola transacción acelera radicalmente la carga masiva de datos. Insertar 1000 registros uno por uno genera una sobrecarga de ~1 segundo. Los mismos 1000 registros en una sola transacción tardan ~5-10 milisegundos. La diferencia se explica porque cada INSERT individual crea una nueva transacción con escritura síncrona en disco.

PRAGMAs de rendimiento

PRAGMA son comandos de SQLite para configurar el comportamiento de la biblioteca. Pragmas de optimización clave: PRAGMA synchronous=NORMAL (reduce la frecuencia de fsync), PRAGMA cache_size=-8000 (asigna 8 MB de caché), PRAGMA temp_store=MEMORY (tablas temporales en memoria). Para aplicaciones móviles con grandes volúmenes de datos, la combinación de estas pragmas acelera las consultas entre 2 y 3 veces.

Otra optimización importante es la precompilación de consultas SQL (prepared statements). Si una consulta se ejecuta repetidamente (por ejemplo, insertando 10000 filas), compilar SQL una vez y reutilizar la sentencia reduce la carga de CPU en un 30-50%. Room y GRDB almacenan en caché automáticamente los prepared statements, pero al usar la API C de SQLite directamente, la compilación debe realizarse manualmente.

kotlin
class UserRepository(private val db: RoomDatabase) {

    suspend fun insertBatch(users: List<User>) {
        db.withTransaction {
            users.chunked(500).forEach { batch ->
                batch.forEach { user ->
                    insertUser(user)
                }
            }
        }
    }
}

La inserción por lotes con withTransaction garantiza que todas las operaciones INSERT se ejecuten dentro de una sola transacción. La división en sublotes (chunked) evita que una sola transacción sea demasiado grande, lo que podría bloquear otros hilos durante un período prolongado. Para la sincronización en segundo plano, un tamaño de sublote de 500 registros proporciona el equilibrio óptimo entre velocidad y capacidad de respuesta de la UI.

Preguntas frecuentes

¿Se puede usar SQLite en múltiples hilos?

Sí, SQLite admite acceso multihilo en modo WAL. Varios hilos pueden leer datos simultáneamente, pero solo uno puede escribir. Room y GRDB gestionan la sincronización automáticamente. En modo rollback journal (predeterminado), la base de datos se bloquea completamente durante cualquier operación de escritura.

¿Cuál es el tamaño máximo de base de datos SQLite en un dispositivo móvil?

El límite de SQLite es de 281 TB (máximo teórico). En la práctica, el tamaño de la base de datos está limitado por la memoria disponible del dispositivo. Para aplicaciones móviles, un tamaño cómodo es de hasta 1-2 GB. Las bases de datos de más de 2 GB ralentizan las copias de seguridad, las actualizaciones a través de App Store y aumentan el consumo de RAM.

¿Son seguros los datos en SQLite?

SQLite no cifra los datos por defecto: cualquier proceso con acceso al archivo puede leerlos. Para el cifrado, utilice SQLCipher (extensión con AES-256), Room con EncryptedDatabase (Android) o Encrypted Core Data en iOS. El cifrado añade un 5-15% de sobrecarga a las operaciones de lectura y escritura de datos.

¿Cuál es la diferencia entre SQLite y MySQL?

SQLite es una biblioteca embebida que no requiere un proceso de servidor. MySQL es un SGBD cliente-servidor con un servidor independiente, usuarios, derechos de acceso y un protocolo de red. SQLite almacena la base de datos en un solo archivo; MySQL la almacena en varios archivos gestionados por el servidor. SQLite es más simple y ligero; MySQL es más potente y escalable.

¿Cómo actualizar el esquema de SQLite sin pérdida de datos?

Para la migración de SQLite, use ALTER TABLE (añadir columnas) o cree una nueva tabla con traslado de datos y eliminación de la tabla antigua. Room automatiza este proceso mediante clases Migration: especifique startVersion, endVersion y las consultas SQL para los cambios de esquema. GRDB y FMDB proporcionan DatabaseMigrator similares.

Resumen

  • SQLite es un SGBD relacional embebido con configuración cero, utilizado en cada aplicación móvil en iOS y Android para el almacenamiento local de datos.
  • Transacciones ACID y modo WAL garantizan la integridad de los datos y el acceso concurrente desde múltiples hilos de la aplicación.
  • Room (Android) y GRDB (iOS) son envoltorios modernos sobre SQLite que simplifican el trabajo con la base de datos mediante APIs type-safe y migraciones automáticas.
  • La arquitectura B-Tree de SQLite garantiza una búsqueda eficiente mediante índices, mientras que las transacciones por lotes y los prepared statements proporcionan un alto rendimiento de escritura.
  • SQLite supera a Realm y Core Data en versatilidad (todas las plataformas), tamaño de biblioteca y ausencia de vendor lock-in.
  • La optimización mediante índices, modo WAL y ajustes PRAGMA acelera las consultas entre 2 y 3 veces en cargas de trabajo móviles típicas.
  • Recomendación — use SQLite como almacenamiento local principal para aplicaciones móviles a través de Room en Android y GRDB en iOS.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también