ObjectBox یک پایگاه داده NoSQL با کارایی بالا است که برای دستگاههای موبایل و لبه بهینه شده است. برخلاف SQLite، از فرمت ذخیرهسازی خود مبتنی بر فایلهای تخت بدون لایه SQL استفاده میکند. طبق ObjectBox Benchmarks, 2024، ObjectBox عملیات درج و خواندن را ۱۰ تا ۱۰۰ برابر سریعتر از SQLite در دستگاههای Android انجام میدهد که آن را به بهترین انتخاب برای برنامههای موبایل با بار بالا تبدیل میکند.
نکات اصلی
ObjectBox یک پایگاه داده in-memory NoSQL است که توسط شرکت آلمانی ObjectBox.io توسعه یافته است. برخلاف پایگاههای داده رابطهای سنتی، ObjectBox اشیاء را مستقیماً در فایلهای تخت با استفاده از فرمت اختصاصی خود SLOT (Super Lightweight Object Tree) ذخیره میکند. این کار سربار ORM و تجزیهگر SQL را حذف میکند. فرمت SLOT برای کار بر روی دستگاههای با حافظه محدود بهینه شده است: دادهها به طور خودکار یکپارچهسازی میشوند و اندازه پایگاه داده به طور متوسط ۴ تا ۶ برابر کوچکتر از پایگاه داده معادل SQLite با همان تعداد رکورد است.
ObjectBox از تمام پلتفرمهای اصلی موبایل پشتیبانی میکند: Android، iOS و Flutter. برای Android تولید کد از طریق ObjectBox Gradle Plugin در دسترس است که موجودیتهای حاشیهنویسی شده را پردازش کرده و کلاسهای Box را برای کار با دادهها ایجاد میکند. برای Flutter از پلاگین بومی با پوشش Dart استفاده میشود. علاوه بر پلتفرمهای موبایل، ObjectBox روی Linux، macOS، Windows و WebAssembly کار میکند که امکان استفاده مجدد از مدل داده بین برنامه موبایل و همگامسازی سرور را فراهم میکند.
طبق دادههای تحقیق ObjectBox (2023)، این پایگاه داده در بیش از ۵۰۰۰ برنامه در Google Play استفاده میشود، از جمله برنامههایی با مخاطب بیش از ۱۰ میلیون کاربر. سناریوهای اصلی: کش کردن دادهها، کار در حالت آفلاین و ذخیره سریهای زمانی (IoT). ObjectBox به ویژه در برنامههای ردیابی سلامت و تناسب اندام محبوب است، جایی که نیاز به ثبت سریع خوانش سنسورها روی دستگاه بدون اتصال دائمی به اینترنت و جمعآوری تحلیل از چندین دستگاه وجود دارد.
ObjectBox به عنوان جایگزینی برای Realm و SQLite برای پلتفرم Android ظهور کرد. اولین نسخه پایدار در سال ۲۰۱۸ منتشر شد. تفاوت کلیدی با Realm — ObjectBox محدودیتهای GPL ندارد (از Apache 2.0 استفاده میکند) و پلتفرمهای بیشتری را پشتیبانی میکند: از دستگاههای موبایل تا سرورهای Linux.
ObjectBox ارائه میدهد: تولید خودکار کلاسهای Box، ایندکسهای داخلی برای جستجوی سریع، تراکنشها با پشتیبانی از بازگشت، کوئریهای واکنشگرا از طریق RxJava و Kotlin Flow، و همچنین همگامسازی بین دستگاهها از طریق ObjectBox Sync (پروتکل اختصاصی). برخلاف Firebase Realtime Database، ObjectBox Sync با مدل همتا به همتا بدون سرور مرکزی کار میکند که تأخیر و هزینههای زیرساخت را کاهش میدهد.
ObjectBox دادهها را در فرمت باینری اختصاصی خود .mdb (ObjectBox Data File) ذخیره میکند. هر موجودیت (Entity) به یک فایل نگاشت میشود، جایی که رکوردها به صورت ترتیبی با افست ثابت ذخیره میشوند. این امکان خواندن و نوشتن اشیاء جداگانه را بدون اسکن کامل فایل فراهم میکند.
برای کار با ObjectBox نیازی به SQL نیست: کوئریها از طریق API روان در کد ساخته میشوند. کامپایلر کلاسهای کمکی MyObjectBox و جعبهها (Box) را تولید میکند که تمام عملیات CRUD را کپسوله میکنند. مدل داده از طریق حاشیهنویسیهای @Entity، @Id، @Index و @Relation توصیف میشود.
// اتصال ObjectBox در 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 | تفاوت |
|---|---|---|---|
| درج (۱۰۰۰ رکورد) | ~۵ ms | ~۱۸۰ ms | x۳۶ سریعتر |
| خواندن (۱۰۰۰ رکورد) | ~۳ ms | ~۷۰ ms | x۲۳ سریعتر |
| بهروزرسانی (۱۰۰۰ رکورد) | ~۶ ms | ~۱۵۰ ms | x۲۵ سریعتر |
| جستجو بر اساس ایندکس | ~۰.۱ ms | ~۲ ms | x۲۰ سریعتر |
| اندازه پایگاه داده (۱۰۰۰ شیء) | ~۲۸ KB | ~۱۱۲ KB | ۴ برابر کوچکتر |
ObjectBox در سناریوهایی که نیاز به کوئریهای پیچیده JOIN، توابع تجمعی (SUM، COUNT با گروهبندی) یا یکپارچهسازی با طرح SQL موجود است، از SQLite عقب میماند. اگر پروژه قبلاً از SQLite با Room ORM استفاده میکند — مهاجرت به ObjectBox نیاز به بازنویسی تمام منطق دسترسی به داده دارد. ObjectBox همچنین از کوئریهای SQL سفارشی پشتیبانی نمیکند — فقط API روان. با این حال برای عملیات معمول CRUD و کش کردن، ObjectBox تا ۱۰۰ برابر افزایش عملکرد میدهد که توسط معیارهای رسمی در دستگاههای Android با نسخههای مختلف سیستم عامل تأیید شده است.
ObjectBox از حاشیهنویسی برای تعریف موجودیتها استفاده میکند. پس از کامپایل، کلاسهای Box با متدهای put، get، remove و query ایجاد میشوند. در زیر عملیات معمول برای مدل Task در برنامه لیست کارها آورده شده است.
هر موجودیت با @Entity حاشیهنویسی میشود. فیلد با @Id کلید اصلی میشود، @Index جستجو بر اساس فیلد را سرعت میبخشد. ObjectBox از تولید خودکار ID با مقدار ۰ پشتیبانی میکند.
@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() حذف میکند. تمام عملیات پایه همزمان هستند و در thread فراخوانیکننده اجرا میشوند.
val taskBox: Box<Task> = boxStore.boxFor(Task::class.java)
// ایجاد
val task = Task(title = "خرید محصولات", priority = 3)
val newId = taskBox.put(task)
// خواندن
val savedTask = taskBox.get(newId)
// بهروزرسانی
savedTask.isCompleted = true
taskBox.put(savedTask)
// حذف
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 با حل تعارض بر اساس last-writer-wins استفاده میکند. Sync برای برنامههایی که نیاز به همگامسازی آفلاین دارند مناسب است: یادداشتها، لیست کارها، دادههای IoT از چندین سنسور. با این حال برای محیط تولید خرید مجوز الزامی است.
// کوئری با چند شرط
val highPriorityIncomplete = taskBox.query()
.greater(Task_.priority, 5)
.equal(Task_.isCompleted, false)
.build()
.find()
// جستجوی زیررشته
val searchResults = taskBox.query()
.contains(Task_.title, "محصول", StringOrder.CASE_INSENSITIVE)
.build()
.find()
سوالات متداول
ObjectBox تحت مجوز Apache 2.0 توزیع میشود که استفاده تجاری بدون محدودیت را مجاز میکند. قابلیت ObjectBox Sync (همگامسازی بینسکویی) اختصاصی است و برای محیط تولید نیاز به خرید مجوز دارد.
BoxStore thread-safe است: چندین thread میتوانند همزمان دادهها را بخوانند. نوشتن در سطح Box مسدود میشود. برای تراکنشهای پیچیده از boxStore.runInTx() استفاده کنید که اتمی بودن گروه عملیات را تضمین میکند.
بله، ObjectBox از Kotlin Multiplatform (KMP) از نسخه ۳.۰ پشتیبانی میکند. اهداف Android، iOS، JVM و Native در دسترس هستند. برای KMP از پلاگین جداگانه Gradle objectbox-kotlin با پشتیبانی expect/actual استفاده میشود.
ObjectBox دادهها را در فایلهای .mdb در دایرکتوری برنامه ذخیره میکند. برای پشتیبانگیری، کل دایرکتوری ObjectBox را از طریق BoxStore.copy() یا پس از فراخوانی boxStore.close() فایلها را به صورت دستی کپی کنید. فایلهای زنده را نمیتوان کپی کرد — این کار دادهها را خراب میکند.
Room — ORM روی SQLite، نیاز به کوئریهای SQL دارد و سربار نگاشت اشیاء را دارد. ObjectBox NoSQL بدون SQL است، بسیار سریعتر است، اما از JOINهای پیچیده پشتیبانی نمیکند و پایگاه داده رابطهای نیست. انتخاب بستگی به وظیفه دارد: برای دادههای رابطهای — Room، برای ذخیرهسازی سریع اشیاء — ObjectBox.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید