Το SQLite είναι μια ενσωματωμένη σχεσιακή βάση δεδομένων που λειτουργεί χωρίς ξεχωριστή διαδικασία εξυπηρετητή και αποθηκεύει ολόκληρη τη βάση σε ένα αρχείο στη συσκευή. Χάρη στη μηδενική ρύθμιση, στο μικρό μέγεθος της βιβλιοθήκης και στην πλήρη υποστήριξη SQL, το SQLite έγινε το πρότυπο για τοπική αποθήκευση δεδομένων σε εφαρμογές για κινητά. Σύμφωνα με τα στοιχεία του SQLite Consortium (2025), αυτό το ΣΔΒΔ χρησιμοποιείται σε πάνω από 4 δισεκατομμύρια συσκευές, συμπεριλαμβανομένου κάθε smartphone σε 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 (διαίρεση σε token), το Parser (κατασκευή AST), το Code Generator (μετατροπή σε byte code) και εκτελείται στην εικονική μηχανή που διαβάζει σελίδες δεδομένων μέσω B-Tree και Pager.
Το SQLite χρησιμοποιεί B-Tree για την αποθήκευση πινάκων και ευρετηρίων. Κάθε πίνακας αποθηκεύεται ως ξεχωριστό B-Tree, όπου οι κόμβοι φύλλου περιέχουν τις γραμμές δεδομένων. Τα ευρετήρια αποθηκεύονται επίσης ως B-Tree, αλλά με κλειδιά στα φύλλα. Το Pager διαχειρίζεται τη φόρτωση σελίδων (από προεπιλογή 4096 bytes) από το αρχείο στη μνήμη, εξασφαλίζοντας συναλλαγές 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. Χάρη στις coroutines (suspend), οι μέθοδοι DAO εκτελούνται ασύγχρονα στο νήμα παρασκηνίου, χωρίς να μπλοκάρουν το UI. Οι τύποι επιστροφής Flow στο @Query ενημερώνουν αυτόματα το αποτέλεσμα όταν αλλάζει ο πίνακας.
FMDB — περίτυλιγμα Objective-C πάνω από το C API του SQLite, ιστορικά η πρώτη δημοφιλής βιβλιοθήκη για iOS. Παρέχει αντικείμενα FMDatabase και FMResultSet για την εκτέλεση ερωτημάτων και τη λήψη αποτελεσμάτων. Το FMDB είναι απλό και μινιμαλιστικό, αλλά δεν υποστηρίζει δομές ειδικές για Swift — optionals, 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 βελτιστοποίησης: PRAGMA synchronous=NORMAL (μειώνει τη συχνότητα fsync), PRAGMA cache_size=-8000 (διαθέτει 8 MB cache), PRAGMA temp_store=MEMORY (προσωρινοί πίνακες στη μνήμη). Για εφαρμογές για κινητά με μεγάλους όγκους δεδομένων, ο συνδυασμός αυτών των PRAGMA επιταχύνει τα ερωτήματα 2-3 φορές.
Μία ακόμα σημαντική βελτιστοποίηση είναι η προ-μεταγλώττιση των SQL ερωτημάτων (prepared statements). Αν ένα ερώτημα εκτελείται πολλές φορές (π.χ. εισαγωγή 10.000 γραμμών), η μία φορά μεταγλώττιση του SQL και στη συνέχεια χρήση του statement μειώνει το φορτίο CPU κατά 30-50%. Το Room και το GRDB αποθηκεύουν αυτόματα στην cache τα prepared statements, αλλά στην άμεση χρήση του C API του SQLite, η μεταγλώττιση πρέπει να γίνει χειροκίνητα.
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. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης