SQLite је уграђена релациона база података која ради без одвојеног серверског процеса и чува целу базу у једној датотеци на уређају. Захваљујући нултој конфигурацији, малој величини библиотеке и пуној подршци за SQL, SQLite је постала стандард за локално складиштење података у мобилним апликацијама. Према подацима SQLite Consortium (2025), овај СБПЗ се користи у преко 4 милијарде уређаја, укључујући сваки паметни телефон на iOS и Android-у.
Главно
SQLite је библиотека у језику C која имплементира релациони СБПЗ без издвојеног сервера. Уграђује се директно у апликацију, чита и пише податке у обичној датотеци на фајл систему уређаја. Величина библиотеке је око 600 KB, што чини SQLite најлакшом потпуно функционалном SQL базом података.
SQLite подржава већи део стандарда SQL:1999, укључујући JOIN, подупите, окидаче, погледе, индексе и прозорске функције. Ограничења се односе на ALTER TABLE (ограничена подршка) и пуне RIGHT/FULL OUTER JOIN. Ипак, за мобилне апликације функционалност SQLite је довољна у 99% случајева локалног складиштења.
Према анкети програмера са Stack Overflow (2025), SQLite је најпопуларнија база података за уграђена решења и заузима треће место по популарности међу свим СБПЗ после MySQL и PostgreSQL. У мобилном развоју, SQLite се користи у свакој апликацији — директно или кроз омотаче.
Zero-configuration — SQLite не захтева инсталацију, подешавање дозвола, креирање корисника или покретање сервиса. Библиотека се повезује са пројектом, а база података се креира позивањем једне функције. То коренито поједностављуће постављање у поређењу са клијент-сервер СБПЗ, које захтевају инсталацију сервера, конфигурацију портова и конфигурацију корисника.
Датотека базе података SQLite је обична вишеплатформна датотека која се може копирати, анализирати, послати путем мреже или вратити из резервне копије. Формат датотеке је стабилан на нивоу API-ја: датотеке SQLite 3 креиране 2004. године отварају се тренутном верзијом библиотеке, што гарантује дугорочну компатибилност података.
Архитектура 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 Journal | WAL (Write-Ahead Logging) |
|---|---|---|
| Читање током писања | Блокира се | Дозвољено (чита старе податке) |
| Перформанса писања | Средња | Висока (секвенцијални упис у WAL) |
| Потрошња диска | Мања (само дневник повлачења) | Већа (WAL + главна база) |
| Опоравак након квара | Повлачење на последњу контролну тачку | Опоравак из WAL-а (подаци се не губе) |
| Препорука | За једнонитне сценарије | За типичне мобилне апликације |
Пребацивање између режима врши се једним SQL упитом: PRAGMA journal_mode=WAL. За мобилне апликације са позадинском синхронизацијом и UI нити која истовремено чита податке, WAL пружа бољу перформансу и одсуство блокирања интерфејса.
SQLite није једина опција за локално складиште података, али је најуниверзалнија. Realm нуди већу брзину директног приступа објектима у меморији, али користи сопствени NoSQL формат и има већу величину библиотеке. Core Data на iOS-у је ORM слој изнад SQLite-а који додаје управљање графом објеката и поништавање операција.
За већину апликација, SQLite остаје оптималан избор захваљујући предвидивој перформанси, нултом зависношчу од произвођача и временски тестираном стабилношчу. Realm и Core Data су оправдани у пројектима са сложеним графовима објеката, реактивним упитима или захтевима за синхронизацију између уређаја.
| Карактеристика | SQLite | Realm | Core Data |
|---|---|---|---|
| Тип базе | Релациона (SQL) | NoSQL (објектна) | ORM (изнад SQLite) |
| Величина библиотеке | ~600 KB | ~4 MB | Уграђена у Apple SDK |
| Перформанса | Средња | Висока (објекти у меморији) | Средња (надометак ORM) |
| Платформе | iOS, Android, Web, Desktop | iOS, Android, Node.js | iOS, macOS |
| Зависност од произвођача | Нема (отворен стандард) | Средња (сопствени формат) | Велика (само Apple) |
Избор између SQLite, Realm и Core Data зависи од платформе, захтева за моделом објеката и стратегије синхронизације. За вишеплатформне пројекте (KMP, Flutter) SQLite остаје једини универзалан избор који ради на свим циљаним платформама без промена у моделу података.
Room — библиотека из Android Jetpack која пружа ORM слој изнад SQLite-а. Room аутоматски генерише SQL упите из анотираних DAO интерфејса, проверава исправност упита у фази компилације и подржава миграције базе података при промени шеме. Room је препоручени начин рада са SQLite на Android-у.
SQLiteOpenHelper — нисконивоаски API за директно управљање SQLite-ом без ORM-а. Класа управља креирањем, отварањем и ажурирањем базе података. SQLiteOpenHelper је погодан за пројекте са једноставним SQL упитима или када је потребна пуна контрола над SQL логиком без апстракције Room-а.
Ентитет у Room-у је анотиран са @Entity, а DAO са @Dao. Room претвара анотиране методе у SQL упите: @Insert генерише INSERT, @Query — SELECT са наведеним SQL. Миграције се додају кроз Migration са навођењем старе и нове верзије шеме. Room проверава SQL у фази компилације, што елиминише синтаксне грешке у производњи.
@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, која садржи упите у времену извршавања ка SQLite-у кроз унутрашњи RoomDatabase. Захваљујући корутинама (suspend), DAO методе се извршавају асинхроно у позадинској нити, не блокирајући UI. Типови повратке Flow у @Query аутоматски ажурирају резултат при промени табеле.
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 дефинише табеле кроз Record класе који испуњавају протоколе FetchableRecord и TableRecord. Упити се пишу у Swift-у са type-safe синтаксом, а не сировим SQL-ом. GRDB такође подржава DatabaseMigrator за верзионирање шеме и миграције између верзија апликације.
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 аутоматски управља везама и транзакцијама, обезбеђујући нитно-безбедан приступ бази из било које нити без ручне синхронизације.
Индекси — најефикаснији начин убрзавања SQLite упита. Индекс се креира на колонама које учествују у WHERE, JOIN и ORDER BY. За табелу са 100 000 записа, претрага по индексираној колони траје милисекунде уместо секунди. Међутим, индекси успоравају INSERT и UPDATE, па њихов број треба да буде уравнотежен са учесталошћу писања.
Шаржно уметање (batch insert) у оквиру једне транзакције коренито убрзава масовно учитавање података. Уметање 1000 записа један по један даје додатни трошак око 1 секунде. Истих 1000 записа у једној транзакцији — око 5–10 милисекунди. Разлика се објашњава чињеницом да сваки појединачни INSERT ствара нову транзакцију са синхроним уписом на диск.
PRAGMA — SQLite команде за подешавање понашања библиотеке. Кључне оптимизационе прагме: PRAGMA synchronous=NORMAL (смањује учесталост fsync), PRAGMA cache_size=-8000 (издваја 8 MB кеша), PRAGMA temp_store=MEMORY (привремене табеле у меморији). За мобилне апликације са великим количинама података, комбинација ових прагми убрзава упите 2–3 пута.
Још једна важна оптимизација је претходна компилација SQL упита (prepared statements). Ако се упит вишеструко извршава (нпр. уметање 10 000 редова), компилација SQL-а једном и затим коришћење statement-а смањује оптерећење CPU-а за 30–50%. Room и GRDB аутоматски кеширају prepared statements, али при директном коришћењу SQLite C API-ја, компилацију треба извршити ручно.
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 подржава вишенитни приступ у WAL режиму. Више нити могу истовремено да читају податке, али само једна може да пише. Room и GRDB аутоматски управљају синхронизацијом. У rollback journal режиму (подразумевано), база је потпуно блокирана при сваком запису.
Ограничење SQLite-а — 281 TB (теоретски максимум). У пракси, величина базе је ограничена доступном меморијом уређаја. За мобилне апликације, комфортна величина је до 1–2 GB. Базе веће од 2 GB успоравају резервно копирање, ажурирање кроз App Store и повећавају потрошњу RAM-а.
SQLite не шифрује податке подразумевано — сваки процес са приступом датотеци може да их чита. За шифрирање користите SQLCipher (проширење са AES-256), Room са EncryptedDatabase (Android) или Encrypted Core Data на iOS-у. Шифрирање додаје 5–15% додатног оптерећења при читању и писању података.
SQLite је уграђена (embedded) библиотека која не захтева серверски процес. MySQL је клијент-сервер СБПЗ са одвојеним сервером, корисницима, правима приступа и мрежним протоколом. SQLite чува базу у једној датотеци, MySQL у више датотека којима управља сервер. SQLite је једноставнија и лакша, MySQL јача и може да се скалира.
За миграцију користите ALTER TABLE (додавање колона) или креирање нове табеле са преносом података и брисањем старе. Room аутоматизује овај процес кроз Migration класе: наведите startVersion, endVersion и SQL упите за измену шеме. GRDB и FMDB пружају сличне DatabaseMigrator.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође