ObjectBox — високопродуктивна NoSQL база даних, оптимізована для мобільних та edge-пристроїв. На відміну від SQLite, вона використовує власний формат зберігання на основі плоских файлів без SQL-прошарку. За даними ObjectBox Benchmarks, 2024, ObjectBox виконує операції вставки та читання в 10–100 разів швидше за SQLite на пристроях Android, що робить його найкращим вибором для високонавантажених мобільних застосунків.
Основне
ObjectBox — in-memory NoSQL база даних, розроблена німецькою компанією ObjectBox.io. На відміну від традиційних реляційних БД, ObjectBox зберігає об'єкти безпосередньо у плоских файлах, використовуючи власний формат SLOT (Super Lightweight Object Tree). Це виключає накладні витрати на ORM та SQL-парсер. SLOT-формат оптимізований для роботи на пристроях з обмеженою пам'яттю: дані дефрагментуються автоматично, а розмір БД в середньому в 4–6 разів менший, ніж еквівалентна SQLite-база за тієї ж кількості записів.
ObjectBox підтримує всі основні мобільні платформи: Android, iOS та Flutter. Для Android доступна генерація коду через ObjectBox Gradle Plugin, який обробляє анотовані сутності та створює Box-класи для роботи з даними. Для Flutter використовується нативний плагін із Dart-обгорткою. Окрім мобільних платформ, ObjectBox працює на Linux, macOS, Windows та WebAssembly, що дозволяє перевикористовувати модель даних між мобільним застосунком та серверною синхронізацією.
За даними дослідження ObjectBox (2023), база даних використовується в більш ніж 5000 застосунках у Google Play, включаючи застосунки з аудиторією понад 10 мільйонів користувачів. Основні сценарії: кешування даних, робота в офлайн-режимі та зберігання часових рядів (IoT). ObjectBox особливо популярний у застосунках для трекінгу здоров'я та фітнесу, де потрібен швидкий запис показань сенсорів на пристрої без постійного інтернет-з'єднання та для збору аналітики з кількох пристроїв.
ObjectBox з'явився як альтернатива Realm та SQLite для платформи Android. Перша стабільна версія вийшла у 2018 році. Ключова відмінність від Realm — ObjectBox не має GPL-обмежень (використовується Apache 2.0) та підтримує більше платформ: від мобільних пристроїв до серверів на Linux.
ObjectBox надає: автоматичну генерацію Box-класів, вбудовані індекси для швидкого пошуку, транзакції з підтримкою відкату, реактивні запити через RxJava та Kotlin Flow, а також синхронізацію між пристроями через ObjectBox Sync (пропрієтарний протокол). На відміну від Firebase Realtime Database, ObjectBox Sync працює за peer-to-peer моделлю без центрального сервера, що знижує затримки та витрати на інфраструктуру.
ObjectBox зберігає дані у власному бінарному форматі .mdb (ObjectBox Data File). Кожна сутність (Entity) маппиться на один файл, де записи зберігаються послідовно з фіксованим зміщенням. Це дозволяє читати та записувати окремі об'єкти без повного сканування файлу.
Для роботи з ObjectBox не потрібен SQL: запити будуються через fluent-API в коді. Компілятор генерує допоміжні класи MyObjectBox та коробки (Box), які інкапсулюють всі операції CRUD. Модель даних описується через анотації @Entity, @Id, @Index та @Relation.
// Connecting ObjectBox in Android
class App: Application() {
lateinit var boxStore: BoxStore
override fun onCreate() {
super.onCreate()
boxStore = MyObjectBox.builder()
.androidContext(this)
.build()
}
}
За даними офіційних бенчмарків, ObjectBox значно перевершує SQLite за швидкістю операцій, особливо при пакетній вставці та масовому читанні. Однак SQLite залишається стандартом де-факто для мобільних застосунків завдяки поширеності та вбудованій підтримці SQL.
| Операція | ObjectBox | SQLite | Різниця |
|---|---|---|---|
| Вставка (1000 записів) | ~5 мс | ~180 мс | ×36 швидше |
| Читання (1000 записів) | ~3 мс | ~70 мс | ×23 швидше |
| Оновлення (1000 записів) | ~6 мс | ~150 мс | ×25 швидше |
| Пошук за індексом | ~0.1 мс | ~2 мс | ×20 швидше |
| Розмір БД (1000 об'єктів) | ~28 KB | ~112 KB | в 4 рази менше |
ObjectBox програє SQLite у сценаріях, де потрібні складні JOIN-запити, агрегатні функції (SUM, COUNT з групуванням) або інтеграція з існуючою SQL-схемою. Якщо проєкт вже використовує SQLite з Room ORM — міграція на ObjectBox потребуватиме переписування всієї логіки доступу до даних. ObjectBox також не підтримує кастомні SQL-запити — тільки fluent-API. Однак для типових операцій CRUD та кешування ObjectBox дає виграш у продуктивності до 100 разів, що підтверджується офіційними бенчмарками на Android-пристроях з різними версіями ОС.
ObjectBox використовує анотації для визначення сутностей. Після компіляції створюються Box-класи з методами put, get, remove та query. Нижче наведено типові операції для моделі Task у застосунку-списку справ.
Кожна сутність анотується @Entity. Поле з @Id стає первинним ключем, @Index прискорює пошук за полем. ObjectBox підтримує автоматичну генерацію ID при значенні 0.
@Entity
data class Task(
@Id var id: Long = 0,
@Index var title: String = "",
var isCompleted: Boolean = false,
var priority: Int = 0
)
Box — основний клас для роботи з сутностями. Метод put() зберігає або оновлює об'єкт, get() читає за ID, remove() видаляє. Всі базові операції синхронні та виконуються на викликаючому потоці.
val taskBox: Box<Task> = boxStore.boxFor(Task::class.java)
// Create
val task = Task(title = "Buy products", priority = 3)
val newId = taskBox.put(task)
// Read
val savedTask = taskBox.get(newId)
// Update
savedTask.isCompleted = true
taskBox.put(savedTask)
// Delete
taskBox.remove(newId)
ObjectBox підтримує реактивні запити через .subscribe(). Підписник отримує сповіщення при будь-яких змінах даних, що відповідають умові запиту. Це зручно для UI, який автоматично оновлює список при додаванні або видаленні елементів.
val query = taskBox.query()
.equal(Task_.isCompleted, false)
.orderDesc(Task_.priority)
.build()
query.subscribe { tasks ->
// tasks — List, обновляется автоматически
updateUi(tasks)
}
ObjectBox підтримує зв'язки між сутностями — To-One, To-Many та Many-to-Many. Зв'язки задаються через анотацію @Relation. На відміну від SQLite, ObjectBox не використовує зовнішні ключі: зв'язки реалізовані через списки ID у плоских файлах, що прискорює навігацію по графу об'єктів.
Зв'язок @Backlink дозволяє пройти від дочірньої сутності до батьківської без окремого поля-посилання. ObjectBox автоматично підтримує зворотне посилання, що виключає дублювання даних та синхронізацію між двома таблицями.
ObjectBox Query Builder дозволяє будувати ланцюжки умов: equal, notEqual, greater, less, in, contains, startsWith. Всі умови комбінуються через and/or. Результат можна відсортувати, обмежити та отримати як List або LazyList (для великих наборів даних).
ObjectBox автоматично індексує поле @Id. Для кастомних індексів використовуйте анотацію @Index на полях, за якими часто виконуються запити. Індекси прискорюють equal- та in-запити, але уповільнюють вставку — не індексуйте поля, за якими пошук не виконується. ObjectBox підтримує складені індекси для фільтрації за кількома полями одночасно. Комбіновані індекси особливо корисні для фільтрів у списках: наприклад, пошук незавершених завдань з високим пріоритетом виконується в десятки разів швидше зі складеним індексом за полями isCompleted та priority.
ObjectBox Sync — пропрієтарна технологія для синхронізації даних між пристроями в реальному часі. Вона використовує протокол на основі WebSocket з conflict resolution за last-writer-wins. Sync підходить для застосунків, яким потрібна офлайн-синхронізація: нотатки, списки завдань, IoT-дані з кількох сенсорів. Однак для продакшну потрібна покупка ліцензії.
// Query with multiple conditions
val highPriorityIncomplete = taskBox.query()
.greater(Task_.priority, 5)
.equal(Task_.isCompleted, false)
.build()
.find()
// Substring search
val searchResults = taskBox.query()
.contains(Task_.title, "product", StringOrder.CASE_INSENSITIVE)
.build()
.find()
Часті запитання
ObjectBox поширюється під ліцензією Apache 2.0, що допускає комерційне використання без обмежень. Функція ObjectBox Sync (міжплатформна синхронізація) — пропрієтарна і вимагає покупки ліцензії для продакшну.
BoxStore потокобезпечний: кілька потоків можуть одночасно читати дані. Запис блокується на рівні Box. Для складних транзакцій використовуйте boxStore.runInTx(), який гарантує атомарність групи операцій.
Так, ObjectBox підтримує Kotlin Multiplatform (KMP) починаючи з версії 3.0. Доступні таргети Android, iOS, JVM та Native. Для KMP використовується окремий Gradle-плагін objectbox-kotlin з підтримкою expect/actual.
ObjectBox зберігає дані у файлах .mdb в директорії застосунку. Для бекапу скопіюйте всю директорію ObjectBox через BoxStore.copy() або вручну скопіюйте файли після виклику boxStore.close(). Живі файли копіювати не можна — це пошкодить дані.
Room — ORM поверх SQLite, вимагає SQL-запитів і має overhead на відображення об'єктів. ObjectBox — NoSQL без SQL, швидший на порядок, але не підтримує складні JOIN і не є реляційною БД. Вибір залежить від задачі: для реляційних даних — Room, для швидкого об'єктного зберігання — ObjectBox.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також