Realm в мобилните приложения: какво е и как работи

Автор: IT Sectr Публикувано: 2026-03-12 Време за четене: 11 мин

Realm е мобилна обектно-ориентирана NoSQL база данни, разработена като алтернатива на SQLite и Core Data за iOS и Android. Данните се съхраняват в собствен формат с директен достъп до обекти в паметта, което осигурява висока скорост на четене и запис. Благодарение на реактивни известия, автоматична синхронизация чрез Realm Sync и кросплатформен модел на данни, Realm се използва на повече от 1 милиард устройства (данни на MongoDB, 2025).

Основни точки

  • Realm е NoSQL обектна база данни за мобилни платформи с директен достъп до данни в оперативната памет.
  • Live Objects обектите на Realm се актуализират автоматично при промяна на данни без ръчно презареждане.
  • Zero-copy данните не се копират между слоевете на приложението, което елиминира допълнителната тежест на ORM.
  • Realm Sync вградена синхронизация между устройства чрез MongoDB Atlas Device Sync.
  • Кросплатформеност моделът на данни се дефинира веднъж за iOS, Android, Flutter и React Native.

Какво е Realm?

Realm е обектно-ориентирана база данни, създадена специално за мобилни приложения. За разлика от SQLite, Realm не използва SQL и релационен модел — данните се съхраняват като живи обекти (Live Objects), до които има директен достъп без посреднически ORM слой. Разработчикът работи с обикновени езикови обекти (Swift, Kotlin, Dart), които автоматично се запазват в базата данни.

Realm се появи през 2014 г. като стартъп Realm Inc., а през 2019 г. беше придобит от MongoDB Inc. Оттогава Realm се развива като MongoDB Realm — част от унифицираната платформа Atlas Device Sync за мобилна синхронизация на данни. Локалната база данни Realm остава безплатна и отворена (лиценз Apache 2.0), докато Realm Sync (облачна синхронизация) се разпространява чрез абонамент.

Според MongoDB Developer Report (2025), Realm се използва в 15% от мобилните приложения като основно локално хранилище. Основните сценарии са приложения с офлайн режим, сложни обектни модели и нужда от синхронизация между устройства, където Realm превъзхожда SQLite по скорост на разработка и удобство при работа с обекти.

Принципи на Realm

Live Objects всеки обект на Realm е свързан с диска чрез memory-mapped файл. Промяна на обект в който и да е поток незабавно се отразява във всички други потоци без ръчно уведомление. Потребителският интерфейс автоматично се прерисува при промяна на данни чрез известия на Realm. Zero-copy Realm не копира данни от базата данни в обекти, обектите са самите данни в паметта.

Как е изграден Realm: архитектура и съхранение

Ядрото на Realm е написано на C++ и използва B+ Tree за индексиране на данни. За разлика от SQLite, където всеки ред е запис в релационна таблица, Realm съхранява обекти като възли в графова структура с директни препратки между тях (forward pointers). Връзките между обекти не са foreign keys, а директни указатели, което елиминира необходимостта от JOIN операции.

Файловете на Realm (разширение .realm) са memory-mapped — операционната система сама управлява зареждането на страници от файла в паметта при достъп. Това позволява на Realm да работи с бази данни, надвишаващи наличната оперативна памет, и осигурява латентност на четене на нивото на родните езикови структури от данни (Swift Array или Kotlin List) за данни, които се побират в RAM.

Zero-copy и Live Objects

Memory-mapped файлове са ключовата технология на Realm. Вместо да копира данни от файла на базата данни в езикови обекти (както прави SQLite чрез sqlite3_step + sqlite3_column_*), Realm картира файла на базата данни директно в адресното пространство на процеса. Езиковите обекти са просто указатели към данни в картираната памет. Промяната на обект променя базата данни на диска без отделно извикване на save.

ХарактеристикаRealm (zero-copy)SQLite (копиране)
ЧетенеДиректен достъп до паметта (наносекунди)Копиране в обект (микросекунди)
ЗаписНезабавен запис в memory-mapped файлsave() с транзакция SQL INSERT/UPDATE
ВръзкиДиректни указатели (forward pointers)Foreign key + JOIN
Консумация на паметФайл + кеш на страниците на ОСОбекти + кеш на страниците на SQLite
Живи обектиДа (автоматична актуализация)Не (изисква се ново fetch)

Консумацията на памет на Realm е по-висока при активно четене (целият файл или голяма част от него е картографиран в паметта), но по-ниска при операции по запис, тъй като не се изисква заделяне на памет за копия на обекти. За бази данни до 1 GB на мобилни устройства, memory-mapped подходът осигурява по-добра обща производителност от SQLite с нейното междинно копиране.

Realm срещу SQLite срещу Core Data: сравнение

SQLite е релационна система за управление на бази данни с SQL и ACID транзакции. Realm е обектно-ориентирана NoSQL база данни с memory-mapped достъп. Core Data е ORM слой на Apple върху SQLite. Всеки от трите подхода има своя област на приложение и силни страни. Realm печели в скоростта на директен достъп до обекти и реактивност, SQLite — в универсалност и зрялост, Core Data — в интеграция с екосистемата на Apple.

Производителността на Realm при четене е с 10-50% по-висока от SQLite благодарение на zero-copy достъпа. При запис Realm също е по-бърз поради липсата на SQL синтактичен анализ и директна промяна на memory-mapped страници. Въпреки това, Realm може да консумира повече оперативна памет при работа с големи бази данни (>500 MB), тъй като файлът е изцяло картографиран в адресното пространство.

КритерийRealmSQLiteCore Data
ТипNoSQL обектна база данниРелационна СУБД (SQL)ORM върху SQLite
Скорост на четенеВисока (zero-copy)СреднаСредна (ORM тежест)
РеактивностLive Objects (вградена)Нужна е обвивка (Room/GRDB)NSFetchedResultsController
СинхронизацияRealm Sync (MongoDB Atlas)Изисква персонализирана реализацияNSPersistentCloudKitContainer
ПлатформиiOS, Android, Flutter, RN, Node.jsiOS, Android, Web, DesktopСамо iOS/macOS
Размер на библиотеката~4 MB~600 KBВграден в SDK

Изборът между Realm и SQLite често се свежда до приоритети: скорост на разработка и реактивност (Realm) срещу контрол и универсалност (SQLite). Realm е особено подходящ за MVP и прототипи, където моделът на данни се променя често и е важно бързо да получавате живи актуализации на UI. SQLite/Room е за предпочитане за зрели продукти с големи обеми данни и сложни аналитични заявки.

Realm на Android: Kotlin SDK

Realm Kotlin SDK е официалната библиотека за Android, написана на Kotlin (не обвивка на Java SDK). Моделът на данни се дефинира чрез класове, наследяващи RealmObject, с анотация @PrimaryKey за уникален идентификатор. Realm Kotlin поддържа Kotlin Coroutines, Flow и KSP (Kotlin Symbol Processing) за генериране на код по време на компилация.

RealmQuery предоставя type-safe API за филтриране без SQL. Заявките се изграждат чрез верижно извикване на методи: queryfiltersortfind. Резултатът може да бъде върнат като списък (с зареждане в паметта) или като Flow (реактивен поток, който се актуализира при промяна на данни). Realm Kotlin също поддържа вложени обекти и списъци (RealmList).

Пример с Realm Kotlin SDK

Моделът на данни на Realm се дефинира като data class, имплементиращ интерфейса RealmObject. Полето _id е маркирано с @PrimaryKey за уникална идентификация. Връзката „един-към-много“ се реализира чрез RealmList — списък от други RealmObject-и. Всички операции за запис (create, update, delete) се изпълняват в рамките на write транзакционен блок.

kotlin
class Project : RealmObject {
    @PrimaryKey
    var _id: ObjectId = ObjectId().generate()
    var name: String = ""
    var tasks: RealmList<Task> = realmListOf()
}

class Task : RealmObject {
    @PrimaryKey
    var _id: ObjectId = ObjectId().generate()
    var title: String = ""
    var isComplete: Boolean = false
}

val config = Realm.Configuration.Builder(
    schema = setOf(Project::class, Task::class)
).build()

val realm = Realm.open(config)
realm.write { transactionRealm ->
    val project = copyToRealm(Project().apply {
        name = "Mobile App"
    })
    project.tasks.add(copyToRealm(Task().apply {
        title = "Design UI"
    }))
}

val projects: Flow<RealmResults<Project>> =
    realm.query<Project>()
        .sort(Project::name, Sort.ASCENDING)
        .asFlow()

Заявка, връщаща Flow, автоматично излъчва нови резултати при всяка промяна на данни в Realm: добавяне, актуализиране или изтриване на Project или Task. Flow подходът се комбинира идеално с Compose: collectAsState() в ViewModel автоматично прекомпозира UI при промяна на данни без ръчно актуализиране на адаптери за списъци или използване на LiveData.

Realm на iOS: Swift SDK

Realm Swift SDK предоставя роден Swift API с поддръжка на async/await, Combine Publishers и Swift Concurrency. Моделите на данни се дефинират като класове, наследяващи Object, с използване на @Persisted за свойства. Realm Swift автоматично актуализира обекти при промени, а известията (NotificationToken) позволяват абониране за промени на отделни обекти или колекции.

@ObservedRealmObject и @ObservedResults са Property Wrapper-и за SwiftUI, които автоматично прерисуват View при промяна на данни в Realm. @ObservedResults работи с резултати от заявки, @ObservedRealmObject — с конкретен обект. И двете свойства прекратяват абонамента при деинициализация на View.

Пример с Realm Swift SDK

SwiftUI интеграцията на Realm е една от силните страни на SDK. Property Wrapper-ът @ObservedResults свързва Realm заявка с визуализацията в SwiftUI. При промяна на всяка задача SwiftUI автоматично прекомпозира списъка. realm.writeAsync изпълнява транзакции във фонов поток без блокиране на UI.

swift
import RealmSwift

class TaskItem: Object, Identifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var title: String = ""
    @Persisted var isDone: Bool = false
    @Persisted var priority: Int = 0
}

struct TaskListView: View {
    @ObservedResults(TaskItem.self,
        sortDescriptor: SortDescriptor(["priority"]))
    var tasks

    var body: some View {
        List {
            ForEach(tasks) { task in
                TaskRow(task: task)
            }
        }
        Button("Добавяне на задача") {
            let realm = try! Realm()
            try! realm.write {
                realm.add(TaskItem(value: ["title": "New task"]))
            }
        }
    }
}

@ObservedResults автоматично управлява жизнения цикъл на Realm заявка: при създаване на View се създава абонамент за промени, при унищожаване — прекратява се. Property Wrapper-ът приема опционален предикат (NSPredicate) и сортиране. Това елиминира необходимостта от ръчно писане на fetch заявки, създаване на ViewModel и абониране за Realm известия.

Сценарии за използване на Realm

Офлайн приложения Realm е идеален за сценарии, където данните трябва да са достъпни без интернет. Вградената синхронизация (Realm Sync с MongoDB Atlas) автоматично разрешава конфликти при свързване към мрежата. Приложението продължава да работи с локални данни, а фоновата синхронизация ги актуализира при наличие на връзка.

Реактивни интерфейси Live Objects и Flow/Combine известия правят Realm удобен избор за приложения с често променящи се данни: чатове, потоци от задачи, споделени документи. UI се актуализира автоматично при добавяне, промяна или изтриване на данни без ръчно извикване на reloadData или invalidate.

Кросплатформени проекти Realm поддържа Kotlin Multiplatform (KMP), Flutter, React Native и Xamarin. Моделът на данни се дефинира веднъж и се използва на всички платформи. Това намалява дублирането на код и гарантира консистентност на схемата на данните между iOS и Android приложения със споделена бизнес логика.

Realm Sync: синхронизация чрез MongoDB Atlas

Realm Sync е облачна услуга, вградена в MongoDB Atlas. Приложението автоматично синхронизира данни между устройствата на потребителя и сървъра. Конфликтите се разрешават според стратегията „last write wins” или чрез персонализирани Conflict Resolution Functions на сървъра. Realm Sync поддържа частична синхронизация (подмножество от данни) за намаляване на трафика.

kotlin
class SyncRepository {
    private val app = App(
        AppConfiguration(
            appId = "my-realm-app-id"
        )
    )

    suspend fun syncData() {
        val user = app.login(Credentials.anonymous())
        val config = SyncConfiguration.Builder(
            user, setOf(Project::class)
        ).build()

        val syncedRealm = Realm.open(config)
        // Автоматичната синхронизация е активна
    }
}

SyncConfiguration конфигурира връзката с MongoDB Atlas и определя набора от синхронизирани модели. След удостоверяване на потребителя, Realm автоматично зарежда данни от облака и ги обединява с локални промени. Синхронизацията работи във фонов поток и не изисква ръчно извикване — достатъчно е да създадете инстанция на Realm със SyncConfiguration.

Често задавани въпроси

Realm безплатен ли е за комерсиална употреба?

Да, локалната Realm база данни е напълно безплатна (лиценз Apache 2.0). Realm Sync (облачна синхронизация) чрез MongoDB Atlas е платена услуга, включена в абонамента Atlas Device Sync. За безплатното ниво на Atlas са достъпни първите 500 MB данни и 1 милион операции на месец.

Може ли да се мигрира от SQLite към Realm?

Да, миграцията е възможна чрез експортиране на данни от SQLite в JSON и импортиране в Realm при първото зареждане на приложението. За големи обеми използвайте поточна миграция: записвайте данни паралелно и в двете бази данни, докато потребителите преминат към новата версия на приложението, след което изтрийте SQLite файла.

Как Realm обработва конфликти при синхронизация?

Realm Sync по подразбиране използва стратегията „last write wins” — последният запис презаписва предишния. За сложни конфликти конфигурирайте персонализирани Conflict Resolution Functions на сървъра MongoDB Atlas, които обединяват промени от различни устройства според бизнес логиката на приложението (например обединяване на стойности вместо замяна).

Поддържа ли Realm агрегатни заявки?

Realm не поддържа SQL агрегации (SUM, AVG, GROUP BY) на ниво база данни. За аналитични заявки се препоръчва експортиране на данни от Realm в MongoDB Atlas чрез Realm Sync и изпълнение на агрегации чрез MongoDB Aggregation Pipeline. За прости преброявания използвайте realm.query<T>().count().

Безопасни ли са данните в Realm?

Realm не криптира данни по подразбиране. За криптиране посочете 64-байтов ключ в конфигурацията: Realm.Configuration(encryptionKey: key). Криптирането използва AES-256 + SHA-2 HMAC и увеличава допълнителната тежест на операциите с 10-20%. Без криптиране, .realm файлът може да бъде прочетен от всеки процес с достъп до файловата система.

Обобщение

  • Realm е обектно-ориентирана NoSQL база данни с memory-mapped достъп, живи обекти и кросплатформен модел на данни за мобилни приложения.
  • Zero-copy архитектурата позволява директно четене на данни от memory-mapped файл без копиране в езикови обекти, което прави Realm с 10-50% по-бърз от SQLite при четене.
  • Live Objects и @ObservedResults (SwiftUI) / Flow (Kotlin) осигуряват автоматични актуализации на UI при промяна на данни без ръчни заявки към базата данни.
  • Realm Sync с MongoDB Atlas предоставя вградена облачна синхронизация с разрешаване на конфликти по стратегията „last write wins”.
  • Кросплатформени SDK поддържат Kotlin Multiplatform, Flutter, React Native — моделът на данни се дефинира веднъж за всички платформи.
  • За аналитични заявки Realm отстъпва на SQLite поради липса на групови агрегации — сложни отчети се изпълняват чрез MongoDB Aggregation Pipeline.
  • Препоръка използвайте Realm за офлайн приложения с чести актуализации на UI и нужда от кросплатформена синхронизация, SQLite/Room за проекти с аналитика и стабилни набори от данни.

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също