SQLite в мобільній розробці: що це таке і як працює

Автор: IT Sectr Опубліковано: 2026-03-11 Час читання: 10 хв

SQLite — вбудована реляційна база даних, яка працює без окремого серверного процесу та зберігає всю базу в одному файлі на пристрої. Завдяки нульовій конфігурації, малому розміру бібліотеки та повній підтримці SQL, SQLite став стандартом для локального зберігання даних у мобільних застосунках. За даними SQLite Consortium (2025), ця СУБД використовується більш ніж у 4 мільярдах пристроїв, включаючи кожен смартфон на iOS та Android.

Головне

  • SQLite — вбудована реляційна СУБД з нульовою конфігурацією та зберіганням даних в одному файлі.
  • ACID-транзакції гарантують цілісність даних навіть при збоях живлення чи краші застосунку.
  • Типізація даних — динамічна: SQLite не вимагає строгого вказання типу колонки при створенні таблиці.
  • Room — ORM-бібліотека Android, що спрощує роботу з SQLite через DAO та анотації.
  • CoreData може використовувати SQLite як Persistent Store на iOS, але додає шар керування об'єктами.

Що таке SQLite?

SQLite — це бібліотека на мові C, що реалізує реляційну СУБД без виділеного сервера. Вона вбудовується безпосередньо в застосунок, читає та записує дані у звичайний файл на файловій системі пристрою. Розмір бібліотеки становить близько 600 КБ, що робить SQLite найлегшою повнофункціональною SQL-базою даних.

SQLite підтримує більшу частину стандарту SQL:1999, включаючи JOIN, підзапити, тригери, представлення, індекси та віконні функції. Обмеження стосуються ALTER TABLE (обмежена підтримка) та повноцінних RIGHT/FULL OUTER JOIN. Тим не менш, для мобільних застосунків функціональності SQLite достатньо в 99% випадків локального зберігання.

За даними опитування розробників від Stack Overflow (2025), SQLite є найпопулярнішою базою даних для вбудованих рішень і займає третє місце за популярністю серед усіх СУБД після MySQL та PostgreSQL. У мобільній розробці SQLite використовується в кожному застосунку — безпосередньо або через обгортки.

Ключові характеристики SQLite

Zero-configuration — SQLite не вимагає встановлення, налаштування прав, створення користувачів або запуску сервісу. Бібліотека підключається до проекту, і база даних створюється викликом однієї функції. Це радикально спрощує розгортання порівняно з клієнт-серверними СУБД, де потрібне встановлення сервера, налаштування портів та конфігурація користувачів.

Файл бази даних SQLite — звичайний крос-платформний файл, який можна скопіювати, проаналізувати, відправити по мережі або відновити з резервної копії. Формат файлу стабільний на рівні API: файли SQLite 3, створені в 2004 році, відкриваються поточною версією бібліотеки, що гарантує довгострокову сумісність даних.

Як влаштований SQLite: архітектура та зберігання

Архітектура SQLite складається з восьми віртуальних машин: Tokenizer, Parser, Code Generator, VM, B-Tree, Pager, OS Interface та Utilities. SQL-запит проходить через Tokenizer (розбивка на токени), Parser (побудова AST), Code Generator (перетворення в байт-код) і виконується на віртуальній машині, яка читає сторінки даних через B-Tree та Pager.

SQLite використовує B-Tree для зберігання таблиць та індексів. Кожна таблиця зберігається як окреме B-Tree, де листові вузли містять рядки даних. Індекси також зберігаються як B-Tree, але з ключами в листях. Pager керує завантаженням сторінок (за замовчуванням 4096 байт) з файлу в пам'ять, забезпечуючи ACID-транзакції через журнал або WAL.

Режими журналювання

WAL (Write-Ahead Logging) — рекомендований режим для мобільних застосунків. Зміни спочатку записуються в окремий WAL-файл, а потім періодично переносяться в основну базу. WAL дозволяє одночасно читати з БД (старі дані) та писати в неї (через WAL), що підвищує продуктивність багатопотокових застосунків. Стандартний журнал (rollback journal) блокує читання при записі.

ПараметрRollback JournalWAL (Write-Ahead Logging)
Читання при записіБлокуєтьсяДозволено (читає старі дані)
Продуктивність записуСередняВисока (послідовний запис у WAL)
Споживання дискаМенше (тільки журнал відкату)Більше (WAL + основна БД)
Відновлення при збоїВідкат до останнього чекпоїнтаВідновлення з WAL (дані не втрачаються)
РекомендаціяДля однопотокових сценаріївДля типових мобільних застосунків

Перемикання між режимами виконується одним SQL-запитом: PRAGMA journal_mode=WAL. Для мобільних застосунків з фоновою синхронізацією та UI-потоком, що одночасно читає дані, WAL забезпечує кращу продуктивність та відсутність блокувань інтерфейсу.

SQLite vs інші БД у мобільній розробці

SQLite — не єдина опція для локального зберігання даних, але найбільш універсальна. Realm пропонує вищу швидкість прямого доступу до об'єктів у пам'яті, але використовує власний NoSQL-формат і має більший розмір бібліотеки. Core Data на iOS — це ORM-шар поверх SQLite, який додає керування графом об'єктів та скасування операцій.

Для більшості застосунків SQLite залишається оптимальним вибором завдяки передбачуваній продуктивності, нульовому vendor lock-in та перевіреній часом стабільності. Realm і Core Data виправдані в проектах зі складними об'єктними графами, реактивними запитами або вимогою до синхронізації між пристроями.

ХарактеристикаSQLiteRealmCore Data
Тип БДРеляційна (SQL)NoSQL (об'єктна)ORM (поверх SQLite)
Розмір бібліотеки~600 КБ~4 МБВбудовано в SDK Apple
ПродуктивністьСередняВисока (об'єкти в пам'яті)Середня (накладні витрати ORM)
ПлатформиiOS, Android, Web, DesktopiOS, Android, Node.jsiOS, macOS
Vendor lock-inНемає (відкритий стандарт)Середній (власний формат)Високий (тільки Apple)

Вибір між SQLite, Realm і Core Data залежить від платформи, вимог до об'єктної моделі та стратегії синхронізації. Для крос-платформних проектів (KMP, Flutter) SQLite залишається єдиним універсальним вибором, що працює на всіх цільових платформах без змін у моделі даних.

SQLite на Android: Room і SQLiteOpenHelper

Room — бібліотека з Android Jetpack, що надає ORM-шар поверх SQLite. Room автоматично генерує SQL-запити з анотованих DAO-інтерфейсів, перевіряє коректність запитів на етапі компіляції та підтримує міграції бази даних при зміні схеми. Room — рекомендований спосіб роботи з SQLite на Android.

SQLiteOpenHelper — низькорівневий API для прямого керування SQLite без ORM. Клас керує створенням, відкриттям та оновленням бази даних. SQLiteOpenHelper підходить для проектів з простими SQL-запитами або коли потрібен повний контроль над SQL-логікою без абстракції Room.

Приклад сутності та DAO для Room

Сутність в Room анотується @Entity, а DAO — @Dao. Room транслює анотовані методи в SQL-запити: @Insert генерує INSERT, @Query — SELECT з вказаним SQL. Міграції додаються через Migration із зазначенням старої та нової версії схеми. Room перевіряє SQL на етапі компіляції, що виключає синтаксичні помилки в production.

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 автоматично генерує імплементацію UserDao_Impl, яка містить runtime-запити до SQLite через внутрішній RoomDatabase. Завдяки корутинам (suspend) DAO-методи виконуються асинхронно на фоновому потоці, не блокуючи UI. Flow-повертальні типи в @Query автоматично оновлюють результат при зміні таблиці.

SQLite на iOS: FMDB і GRDB

FMDB — Objective-C обгортка над SQLite C API, історично перша популярна бібліотека для iOS. Надає об'єкти FMDatabase та FMResultSet для виконання запитів і отримання результатів. FMDB проста та мінімалістична, але не підтримує Swift-специфічні конструкції — опціонали, Codable, async/await.

GRDB — сучасна Swift-бібліотека для роботи з SQLite. Надає type-safe API, підтримку Codable, Combine Publishers, async/await, міграції та спостереження за змінами в реальному часі. GRDB є кращою для нових проектів на Swift завдяки повній інтеграції зі Swift Concurrency та кращій читабельності коду.

Приклад GRDB на Swift

GRDB визначає таблиці через Record-класи, що відповідають протоколам FetchableRecord та TableRecord. Запити пишуться на Swift з type-safe синтаксисом, а не сирим SQL. GRDB також підтримує DatabaseMigrator для версіонування схеми та міграцій між версіями застосунку.

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 використовує WAL-режим SQLite для конкурентного читання. Багато читачів можуть одночасно звертатися до бази, поки один писатель оновлює дані через WAL. GRDB автоматично керує з'єднаннями та транзакціями, забезпечуючи thread-safe доступ до бази з будь-якого потоку без ручної синхронізації.

Оптимізація продуктивності SQLite

Індекси — найефективніший спосіб прискорення SQLite-запитів. Індекс створюється на колонках, що беруть участь у WHERE, JOIN та ORDER BY. Для таблиці з 100000 записів пошук за індексованою колонкою виконується за мілісекунди замість секунд. Однак індекси сповільнюють INSERT та UPDATE, тому їх кількість має бути збалансована з частотою запису.

Пакетна вставка (batch insert) в рамках однієї транзакції радикально прискорює масове завантаження даних. Вставка 1000 записів по одній дає накладні витрати ~1 секунду. Ті ж 1000 записів в одній транзакції — ~5-10 мілісекунд. Різниця пояснюється тим, що кожна окрема INSERT створює нову транзакцію з синхронним записом на диск.

Прагми продуктивності

PRAGMA — SQLite-команди для налаштування поведінки бібліотеки. Ключові оптимізаційні прагми: PRAGMA synchronous=NORMAL (знижує частоту fsync), PRAGMA cache_size=-8000 (виділяє 8 МБ кешу), PRAGMA temp_store=MEMORY (тимчасові таблиці в пам'яті). Для мобільних застосунків з великими обсягами даних комбінація цих прагм прискорює запити в 2-3 рази.

Ще одна важлива оптимізація — попередня компіляція SQL-запитів (prepared statements). Якщо запит виконується багаторазово (наприклад, вставка 10000 рядків), компіляція SQL один раз з подальшим використанням statement знижує завантаження CPU на 30-50%. Room і GRDB автоматично кешують prepared statements, але при прямому використанні SQLite C API компіляцію потрібно виконувати вручну.

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)
                }
            }
        }
    }
}

Пакетна вставка з withTransaction гарантує, що всі INSERT виконуються в рамках однієї транзакції. Розбивка на підбатчі (chunked) запобігає надто великому розміру однієї транзакції, яка могла б заблокувати інші потоки на тривалий час. Для фонової синхронізації розмір підбатча 500 записів дає оптимальний баланс швидкості та чуйності UI.

Часто задавані питання

Чи можна використовувати SQLite на кількох потоках?

Так, SQLite підтримує багатопотоковий доступ у режимі WAL. Кілька потоків можуть одночасно читати дані, але писати може тільки один. Room і GRDB керують синхронізацією автоматично. У режимі rollback journal (за замовчуванням) база повністю блокується при будь-якому записі.

Який максимальний розмір бази SQLite на мобільному пристрої?

Обмеження SQLite — 281 ТБ (теоретичний максимум). На практиці розмір бази обмежений доступною пам'яттю пристрою. Для мобільних застосунків комфортний розмір — до 1-2 ГБ. Бази більше 2 ГБ сповільнюють резервне копіювання, оновлення через App Store та збільшують споживання оперативної пам'яті.

Чи безпечні дані в SQLite?

SQLite не шифрує дані за замовчуванням — будь-який процес з доступом до файлу може їх прочитати. Для шифрування використовуйте SQLCipher (розширення з AES-256), Room з EncryptedDatabase (Android) або Encrypted Core Data на iOS. Шифрування додає 5-15% накладних витрат на читання та запис даних.

Чим відрізняється SQLite від MySQL?

SQLite — вбудована (embedded) бібліотека, що не потребує серверного процесу. MySQL — клієнт-серверна СУБД з окремим сервером, користувачами, правами доступу та мережевим протоколом. SQLite зберігає базу в одному файлі, MySQL — у кількох файлах, керованих сервером. SQLite простіший і легший, MySQL потужніший і масштабованіший.

Як оновити схему SQLite без втрати даних?

Для міграції SQLite використовуйте ALTER TABLE (додавання колонок) або створення нової таблиці з перенесенням даних та видаленням старої. Room автоматизує цей процес через класи Migration: вкажіть startVersion, endVersion та SQL-запити для зміни схеми. GRDB і FMDB надають аналогічні DatabaseMigrator.

Підсумки

  • SQLite — вбудована реляційна СУБД з нульовою конфігурацією, що використовується в кожному мобільному застосунку на iOS та Android для локального зберігання даних.
  • ACID-транзакції та WAL-режим забезпечують цілісність даних і конкурентний доступ з кількох потоків застосунку.
  • Room (Android) та GRDB (iOS) — сучасні обгортки над SQLite, що спрощують роботу з базою через type-safe API та автоматичні міграції.
  • B-Tree архітектура SQLite забезпечує ефективний пошук за індексами, а пакетні транзакції та prepared statements — високу продуктивність запису.
  • SQLite перевершує Realm і Core Data за універсальністю (всі платформи), розміром бібліотеки та відсутністю vendor lock-in.
  • Оптимізація через індекси, WAL-режим та PRAGMA-налаштування прискорює запити в 2-3 рази на типових мобільних навантаженнях.
  • Рекомендація — використовуйте SQLite як основне сховище для локальних даних мобільного застосунку через Room на Android та GRDB на iOS.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також