Ang SQLite ay isang naka-embed na relational database na gumagana nang walang hiwalay na proseso ng server at iniimbak ang buong database sa isang file sa device. Dahil sa zero configuration, maliit na laki ng library, at buong suporta sa SQL, ang SQLite ay naging pamantayan para sa lokal na pag-iimbak ng data sa mga mobile application. Ayon sa data ng SQLite Consortium (2025), ang DBMS na ito ay ginagamit sa mahigit 4 bilyong device, kabilang ang bawat smartphone sa iOS at Android.
Mga Pangunahing Punto
SQLite ay isang library sa wikang C na nagpapatupad ng relational DBMS nang walang dedikadong server. Ito ay direktang naka-embed sa application, nagbabasa at nagsusulat ng data sa isang ordinaryong file sa file system ng device. Ang laki ng library ay humigit-kumulang 600 KB, na ginagawang pinakamagaan na ganap na gumaganang SQL database ang SQLite.
Sinusuportahan ng SQLite ang karamihan ng pamantayang SQL:1999, kabilang ang JOIN, subquery, trigger, view, index, at window functions. Ang mga limitasyon ay nauugnay sa ALTER TABLE (limitadong suporta) at buong RIGHT/FULL OUTER JOIN. Gayunpaman, para sa mga mobile application, sapat ang functionality ng SQLite sa 99% ng mga kaso ng lokal na pag-iimbak.
Ayon sa survey ng developer ng Stack Overflow (2025), ang SQLite ay ang pinakasikat na database para sa mga naka-embed na solusyon at pumapangatlo sa kasikatan sa lahat ng DBMS pagkatapos ng MySQL at PostgreSQL. Sa mobile development, ginagamit ang SQLite sa bawat application — direkta o sa pamamagitan ng mga wrapper.
Zero-configuration — hindi kailangan ng SQLite ang pag-install, pagsasaayos ng mga pahintulot, paggawa ng mga user, o pagsisimula ng serbisyo. Ang library ay ikinokonekta sa proyekto, at ang database ay ginagawa sa pamamagitan ng pagtawag sa isang function. Ito ay radikal na nagpapasimple ng deployment kumpara sa client-server DBMS na nangangailangan ng pag-install ng server, pagsasaayos ng port, at pagsasaayos ng user.
Ang file ng database ng SQLite ay isang ordinaryong cross-platform file na maaaring kopyahin, suriin, ipadala sa network, o ibalik mula sa backup. Ang format ng file ay stable sa antas ng API: ang mga file ng SQLite 3 na ginawa noong 2004 ay nagbubukas sa kasalukuyang bersyon ng library, na ginagarantiyahan ang pangmatagalang compatibility ng data.
Ang arkitektura ng SQLite ay binubuo ng walong virtual machine: Tokenizer, Parser, Code Generator, VM, B-Tree, Pager, OS Interface, at Utilities. Ang SQL query ay dumadaan sa Tokenizer (paghahati sa mga token), Parser (pagbuo ng AST), Code Generator (conversion sa byte code) at isinasagawa sa virtual machine na nagbabasa ng mga pahina ng data sa pamamagitan ng B-Tree at Pager.
Gumagamit ang SQLite ng B-Tree para sa pag-iimbak ng mga table at index. Ang bawat table ay iniimbak bilang hiwalay na B-Tree, kung saan ang mga leaf node ay naglalaman ng mga row ng data. Ang mga index ay iniimbak din bilang B-Tree, ngunit may mga key sa mga leaf. Pinamamahalaan ng Pager ang pag-load ng mga page (default 4096 bytes) mula sa file papunta sa memory, na tinitiyak ang mga transaksyong ACID sa pamamagitan ng journal o WAL.
WAL (Write-Ahead Logging) — ang inirerekomendang mode para sa mga mobile application. Ang mga pagbabago ay unang isinusulat sa isang hiwalay na WAL file, pagkatapos ay pana-panahong inililipat sa pangunahing database. Pinapayagan ng WAL ang sabay-sabay na pagbabasa mula sa database (lumang data) at pagsusulat dito (sa pamamagitan ng WAL), na nagpapabuti sa performance ng mga multi-threaded application. Ang karaniwang journal (rollback journal) ay humaharang sa pagbabasa habang nagsusulat.
| Parameter | Rollback Journal | WAL (Write-Ahead Logging) |
|---|---|---|
| Pagbabasa habang nagsusulat | Naka-block | Pinapayagan (binabasa ang lumang data) |
| Performance ng pagsulat | Katamtaman | Mataas (sequential write sa WAL) |
| Paggamit ng disk | Mas kaunti (rollback journal lang) | Mas marami (WAL + pangunahing database) |
| Pagbawi pagkatapos ng crash | Bumalik sa huling checkpoint | Pagbawi mula sa WAL (hindi nawawala ang data) |
| Rekomendasyon | Para sa single-thread scenario | Para sa tipikal na mobile application |
Ang paglipat sa pagitan ng mga mode ay ginagawa sa isang SQL query: PRAGMA journal_mode=WAL. Para sa mga mobile application na may background synchronization at UI thread na sabay na nagbabasa ng data, nagbibigay ang WAL ng mas mahusay na performance at walang pag-block ng interface.
Ang SQLite ay hindi lamang ang opsyon para sa lokal na pag-iimbak ng data, ngunit ito ang pinaka-unibersal. Ang Realm ay nag-aalok ng mas mataas na bilis ng direktang pag-access sa mga object sa memory, ngunit gumagamit ng sarili nitong NoSQL format at may mas malaking laki ng library. Ang Core Data sa iOS ay isang ORM layer sa ibabaw ng SQLite na nagdaragdag ng pamamahala ng graph ng object at pag-undo ng mga operasyon.
Para sa karamihan ng mga application, ang SQLite ay nananatiling pinakamainam na pagpipilian dahil sa predictable performance, walang vendor lock-in, at nasubok na katatagan. Ang Realm at Core Data ay makatwiran sa mga proyektong may kumplikadong mga graph ng object, reactive query, o pangangailangan para sa synchronization sa pagitan ng mga device.
| Katangian | SQLite | Realm | Core Data |
|---|---|---|---|
| Uri ng database | Relational (SQL) | NoSQL (object-oriented) | ORM (sa ibabaw ng SQLite) |
| Laki ng library | ~600 KB | ~4 MB | Naka-embed sa Apple SDK |
| Performance | Katamtaman | Mataas (mga object sa memory) | Katamtaman (overhead ng ORM) |
| Mga platform | iOS, Android, Web, Desktop | iOS, Android, Node.js | iOS, macOS |
| Vendor lock-in | Wala (bukas na pamantayan) | Katamtaman (sariling format) | Mataas (Apple lang) |
Ang pagpili sa pagitan ng SQLite, Realm, at Core Data ay depende sa platform, mga kinakailangan ng object model, at diskarte sa synchronization. Para sa mga proyektong cross-platform (KMP, Flutter), ang SQLite ay nananatiling tanging unibersal na pagpipilian na gumagana sa lahat ng target na platform nang walang pagbabago sa modelo ng data.
Room — isang library mula sa Android Jetpack na nagbibigay ng ORM layer sa ibabaw ng SQLite. Awtomatikong bumubuo ang Room ng mga SQL query mula sa mga na-annotate na DAO interface, sinusuri ang kawastuhan ng query sa yugto ng compilation, at sumusuporta sa mga migration ng database kapag nagbago ang schema. Ang Room ay ang inirerekomendang paraan ng pagtatrabaho sa SQLite sa Android.
SQLiteOpenHelper — mababang antas na API para sa direktang pamamahala ng SQLite nang walang ORM. Pinamamahalaan ng klase ang paggawa, pagbubukas, at pag-update ng database. Ang SQLiteOpenHelper ay angkop para sa mga proyektong may simpleng SQL query o kapag kailangan ang buong kontrol sa SQL logic nang walang abstraction ng Room.
Ang entity sa Room ay na-annotate ng @Entity, at ang DAO ay ng @Dao. Isinasalin ng Room ang mga na-annotate na pamamaraan sa mga SQL query: ang @Insert ay bumubuo ng INSERT, ang @Query — SELECT na may tinukoy na SQL. Ang mga migration ay idinaragdag sa pamamagitan ng Migration na may pagtukoy ng luma at bagong bersyon ng schema. Sinusuri ng Room ang SQL sa yugto ng compilation, na nag-aalis ng mga syntax error sa produksyon.
@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)
}
Awtomatikong bumubuo ang Room ng implementasyon ng UserDao_Impl, na naglalaman ng mga runtime query sa SQLite sa pamamagitan ng panloob na RoomDatabase. Dahil sa mga coroutine (suspend), ang mga pamamaraan ng DAO ay isinasagawa nang asynchronously sa background thread, nang hindi hinaharangan ang UI. Ang mga uri ng pagbabalik ng Flow sa @Query ay awtomatikong nag-a-update ng resulta kapag nagbago ang table.
FMDB — Objective-C wrapper sa ibabaw ng C API ng SQLite, sa kasaysayan ang unang sikat na library para sa iOS. Nagbibigay ng mga FMDatabase at FMResultSet object para sa pagpapatakbo ng mga query at pagkuha ng mga resulta. Ang FMDB ay simple at minimalist, ngunit hindi sumusuporta sa mga konstruksyong partikular sa Swift — optionals, Codable, async/await.
GRDB — modernong Swift library para sa pagtatrabaho sa SQLite. Nagbibigay ng type-safe API, suporta para sa Codable, Combine Publishers, async/await, migration, at real-time na pagsubaybay sa pagbabago. Mas pinipili ang GRDB para sa mga bagong proyekto sa Swift dahil sa buong integrasyon sa Swift Concurrency at mas mahusay na pagiging nababasa ng code.
Ang GRDB ay tumutukoy ng mga table sa pamamagitan ng Record class na sumusunod sa mga protocol na FetchableRecord at TableRecord. Ang mga query ay isinusulat sa Swift na may type-safe syntax, hindi sa raw SQL. Sinusuportahan din ng GRDB ang DatabaseMigrator para sa pag-version ng schema at migration sa pagitan ng mga bersyon ng application.
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)
}
Ang DatabasePool ay gumagamit ng WAL mode ng SQLite para sa concurrent na pagbabasa. Maraming mambabasa ang maaaring sabay na ma-access ang database, habang ang isang manunulat ay nag-a-update ng data sa pamamagitan ng WAL. Awtomatikong pinamamahalaan ng GRDB ang mga koneksyon at transaksyon, na nagbibigay ng thread-safe na pag-access sa database mula sa anumang thread nang walang manual na synchronization.
Mga Index — ang pinakamabisang paraan upang pabilisin ang mga query ng SQLite. Ang index ay ginagawa sa mga column na nakikilahok sa WHERE, JOIN, at ORDER BY. Para sa isang table na may 100,000 record, ang paghahanap sa isang naka-index na column ay tumatagal ng millisecond sa halip na segundo. Gayunpaman, pinapabagal ng mga index ang INSERT at UPDATE, kaya ang kanilang bilang ay dapat balansehin sa dalas ng pagsulat.
Batch insert sa loob ng isang transaksyon ay radikal na nagpapabilis ng mass data loading. Ang pagpasok ng 1000 record nang paisa-isa ay nagbibigay ng overhead na ~1 segundo. Ang parehong 1000 record sa isang transaksyon — ~5–10 millisecond. Ang pagkakaiba ay ipinaliwanag sa pamamagitan ng katotohanan na ang bawat hiwalay na INSERT ay lumilikha ng bagong transaksyon na may synchronous write sa disk.
PRAGMA — mga command ng SQLite para sa pagsasaayos ng pag-uugali ng library. Mga pangunahing optimization PRAGMA: PRAGMA synchronous=NORMAL (nagbabawas ng dalas ng fsync), PRAGMA cache_size=-8000 (naglalaan ng 8 MB cache), PRAGMA temp_store=MEMORY (mga pansamantalang table sa memory). Para sa mga mobile application na may malaking volume ng data, ang kumbinasyon ng mga PRAGMA na ito ay nagpapabilis ng mga query nang 2–3 beses.
Ang isa pang mahalagang optimization ay ang pre-compilation ng mga SQL query (prepared statements). Kung ang isang query ay paulit-ulit na isinasagawa (halimbawa, pagpasok ng 10,000 row), ang isang beses na compilation ng SQL at pagkatapos ay paggamit ng statement ay nagbabawas ng CPU load ng 30–50%. Awtomatikong ni-cacache ng Room at GRDB ang mga prepared statement, ngunit sa direktang paggamit ng SQLite C API, ang compilation ay dapat gawin nang manu-mano.
class UserRepository(private val db: RoomDatabase) {
suspend fun insertBatch(users: List<User>) {
db.withTransaction {
users.chunked(500).forEach { batch ->
batch.forEach { user ->
insertUser(user)
}
}
}
}
}
Ang batch insert na may withTransaction ay ginagarantiyahan na ang lahat ng INSERT ay isinasagawa sa loob ng isang transaksyon. Ang paghahati sa mga sub-batch (chunked) ay pumipigil sa isang napakalaking transaksyon na maaaring mag-block ng iba pang thread nang matagal. Para sa background synchronization, ang sub-batch na laki ng 500 record ay nagbibigay ng optimal na balanse sa pagitan ng bilis at pagtugon ng UI.
Mga Madalas Itanong
Oo, ang SQLite ay sumusuporta sa multi-thread access sa WAL mode. Maraming thread ang maaaring sabay na magbasa ng data, ngunit isa lamang ang maaaring sumulat. Awtomatikong pinamamahalaan ng Room at GRDB ang synchronization. Sa rollback journal mode (default), ang database ay ganap na naka-block sa anumang pagsulat.
Ang limitasyon ng SQLite — 281 TB (theoretical maximum). Sa praktika, ang laki ng database ay limitado ng available na memory ng device. Para sa mga mobile application, ang komportableng laki ay hanggang 1–2 GB. Ang mga database na mas malaki sa 2 GB ay nagpapabagal ng backup, pag-update sa pamamagitan ng App Store, at nagpapataas ng pagkonsumo ng RAM.
Ang SQLite ay hindi nag-e-encrypt ng data bilang default — anumang proseso na may access sa file ay maaaring magbasa nito. Para sa encryption, gamitin ang SQLCipher (extension na may AES-256), Room na may EncryptedDatabase (Android) o Encrypted Core Data sa iOS. Ang encryption ay nagdaragdag ng 5–15% overhead sa pagbabasa at pagsusulat ng data.
Ang SQLite ay isang naka-embed (embedded) na library na hindi nangangailangan ng proseso ng server. Ang MySQL ay isang client-server DBMS na may hiwalay na server, mga user, mga karapatan sa pag-access, at network protocol. Iniimbak ng SQLite ang database sa isang file, ang MySQL sa maraming file na pinamamahalaan ng server. Ang SQLite ay mas simple at magaan, ang MySQL ay mas malakas at nasusukat.
Para sa migration, gamitin ang ALTER TABLE (pagdaragdag ng column) o paggawa ng bagong table na may paglilipat ng data at pagtanggal ng luma. Ina-automate ng Room ang prosesong ito sa pamamagitan ng mga klase ng Migration: tukuyin ang startVersion, endVersion, at mga SQL query para sa pagbabago ng schema. Ang GRDB at FMDB ay nagbibigay ng katulad na DatabaseMigrator.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din