سِکوالایز در برابر پرایزما

شروع

در حال حاضر در eBay، من در حال مهاجرت ابزارهای داخلی‌مان از استفاده از MongoDB به Postgres هستم. پروژه‌ای که بسیار دشوار است، اما مشتاقم که مستقیم به سراغش بروم. هنگام تحقیق، متوجه شدم که برای کُدبیس ما، استفاده از یک ORM بهترین گزینه خواهد بود، چون کُدبیس از قبل برای استفاده از Mongoose طراحی شده بود. اما حالا چالش این است که کدام ORM برای کُدبیس ما بهترین خواهد بود؟ در این وبلاگ، به این پرسش می‌پردازم. لطفاً توجه داشته باشید که به دلیل ماهیت ارتباطم با کارفرمایم، نمی‌توانم همه چیز را در این وبلاگ افشا کنم.

الزامات

پس از تحلیل دقیق نیازهای پروژه، معیارهای ضروری زیر را تعیین کردم که هر راه‌حل ORM باید آن‌ها را برآورده کند:

  • یک بستهٔ JavaScript باشد؛ چون بیشتر کُدها در JavaScript نوشته شده‌اند
  • باید از Postgres و بیشتر قابلیت‌های آن پشتیبانی کند
  • عملکرد آن باید دست‌کم هم‌سطح Mongoose یا بهتر از آن باشد
  • باید متن‌باز و نگه‌داری‌شده باشد

ORMها

پس از انجام تحقیقات بسیار، مشخص کردم که سه ORM برتر که با این الزامات سازگارند عبارت‌اند از: Sequelize، Prisma، و TypeORM. در نهایت تصمیم گرفتم فقط روی Sequelize و Prisma تمرکز کنم، چون به دلیل مهلت‌ها زمان کافی برای آزمایش کامل سه ORM مختلف را نداشتم.

محیط آزمایش

برای محیط آزمایشم، Postgres را از طریق Docker اجرا کردم. بزرگ‌ترین و پیچیده‌ترین مجموعه‌دادهٔ خودمان را برداشتم، آن را از ساختار سندی به ساختار جدولی تبدیل کردم، و به نمونهٔ محلی Postgres خودم اضافه کردم. مجموعه‌داده را با استفاده از ستون‌ها، روابط یک‌به‌یک، روابط یک‌به‌چند، و چند ستون JSONB تبدیل کردم.

از آنجا، کُد JavaScript می‌نوشتم که از آن ORM مشخص استفاده می‌کرد و اندازه‌گیری می‌کردم:

  • ایجاد یک ورودی چقدر زمان می‌برد
  • به‌روزرسانی یک ورودی چقدر زمان می‌برد
  • به‌روزرسانی یک ورودی تو‌در‌تو چقدر زمان می‌برد (رابطه و/یا کلید-مقدار در یک JSON)
  • حذف یک ورودی چقدر زمان می‌برد
  • پرس‌وجو/دریافت یک ورودی چقدر زمان می‌برد

برای هر محیط آزمایشی ORM، مخزن‌هایی ایجاد کردم. خیلی دوست داشتم این مخزن‌ها را به اشتراک بگذارم، اما از نظر فنی متعلق به eBay هستند، بنابراین نمی‌توانم آن‌ها را به اشتراک بگذارم.

نتایج

حدود ۱۵ مه ۲۰۲۳، تصمیم گرفتم که Sequelize برای مورد استفادهٔ ما ORM بهتری است و همان ORMی خواهد بود که برای مهاجرت ما از MongoDB به Postgres استفاده می‌شود. در نهایت، Sequelize را انتخاب کردم زیرا:

  • «واقعاً متن‌باز» بود و توسط یک استارتاپِ تأمین‌مالی‌شده نگه‌داری نمی‌شد.
  • بیشتر قابلیت‌های Postgres را پشتیبانی می‌کرد.
  • عملکرد خوبی داشت، به‌ویژه در مقایسه با Prisma.
  • مستندات خوبی دارد، هرچند به خوبی مستندات Prisma نیست.

من روی Sequelize به نتیجه رسیدم، اما همچنین برای هر ORMی که آزمایش کردم یک فهرست مزایا و معایب تهیه کردم به این امید که به مردم کمک کند بهتر تعیین کنند آیا Sequelize یا Prisma برای مورد استفادهٔ شما مناسب خواهد بود یا نه.

مزایا و معایب Sequelize

مزایا:

  • یک تابع sync() دارد که به‌طور خودکار جدول‌ها را برای شما ایجاد و مدیریت می‌کند
  • می‌تواند joinهای پیچیده را مدیریت کند (دادهٔ تو‌در‌تو)
  • گزینه‌های فیلتر فراوانی را پشتیبانی می‌کند (مانند Regex)
  • نمایش مدل/اسکیما به‌صورت JavaScript خام و با استفاده از classها انجام می‌شود که بسیار قابل سفارشی‌سازی‌اند.
  • Sequelize اتصال‌ها را برای پایگاه‌داده(های) انتخابی شما مدیریت می‌کند.
  • Sequelize از چندین اتصالِ خواندن پشتیبانی می‌کند
  • از پرس‌وجوهای SQL خام پشتیبانی می‌کند.
  • تا تاریخ ۱۵ مه ۲۰۲۳:
    • در NPM، Sequelize آخرین‌بار «۱۴ روز پیش» به‌روزرسانی شده بود و ۱٬۵۰۵٬۸۳۵ دانلود هفتگی دارد.
    • در GitHub، Sequelize آخرین‌بار «دیروز» به‌روزرسانی شده بود، 4.2k فورک و 27.9k ستاره دارد.
    • Sequelize مجوز MIT دارد و بیش از ۱۰ سال است که متن‌باز بوده است. بنابراین به‌احتمال زیاد در آیندهٔ قابل پیش‌بینی متن‌باز باقی خواهد ماند.

معایب:

  • نمایش مدل/اسکیما می‌تواند بسیار پیچیده و حجیم شود. برای مثال، نمایش Mongoose از مجموعه‌دادهٔ بزرگ ما حدود ۲۶۲ خط بود (شامل فاصله‌ها). همان مجموعه‌داده که از طریق Sequelize نمایش داده شد ۵۶۴ خط بود (شامل فاصله‌ها).
  • نحوِ Sequelize در برخی موارد واقعاً گیج‌کننده و پیچیده می‌شود.
  • مهاجرت پایگاه‌دادهٔ شما (ویرایش آن) بسیار دردسرساز است. می‌توانید از sequelize-cli برای تولید اسکریپت‌های الگوی مهاجرت JavaScript استفاده کنید. اما به‌نظر می‌رسد این وضعیت تقریباً در مورد همهٔ ORMها یکسان باشد. مهاجرت در یک پایگاه‌دادهٔ رابطه‌ای در بیشتر موارد آسان نیست.
  • مستندات آن چندان عالی نیست. بهتر شده است اما هنوز به کار نیاز دارد. با این حال، با ابزارهایی مانند ChatGPT، این دیگر به‌اندازهٔ گذشته مسئلهٔ بزرگی نیست، چون ChatGPT احتمالاً به دلیل وجود Sequelize در طول یک دهه، درک بسیار خوبی از Sequelize دارد.
  • Sequelize در مقایسه با Prisma به نوع‌ها به اندازهٔ کافی حساس نیست، که می‌تواند به مشکلاتی منجر شود.
  • از TypeScript به‌خوبی پشتیبانی نمی‌کند، که برای پروژهٔ من مشکلی نیست اما برای بسیاری از پروژه‌های دیگر می‌تواند مشکل بزرگی باشد.

مزایا و معایب Prisma

مزایا:

  • زبان اسکیماي خودش را دارد. این یعنی می‌توانید اسکیما/مدل خود را آسان‌تر و تمیزتر بسازید. برای مثال، نمایش Mongoose از مجموعه‌دادهٔ بزرگ ما حدود ۲۶۲ خط بود (شامل فاصله‌ها). اما همان مجموعه‌داده که توسط Prisma نمایش داده شد فقط ۲۲۱ خط بود (شامل فاصله‌ها).
  • Prisma یک ابزار CLI دارد که ایجاد و مهاجرت (تغییر) پایگاه‌دادهٔ شما را آسان‌تر می‌کند. که بسیار راحت است. این یک راه‌حل جادویی نیست، اما بهترین چیزی است که تا اینجا از یک ORM دیده‌ام.
  • از پرس‌وجوهای SQL خام پشتیبانی می‌کند.
  • کُد Prisma تمیز و ساده است. هنوز هم باید نحو Prisma را یاد بگیرید و با آن خو بگیرید، اما فهمیدن آن خیلی آسان‌تر از نحو Sequelize است.
  • Prisma یک کلاینت دارد که به‌طور خودکار query builderها را برای Node.js و TypeScript تولید می‌کند.
  • مستندات بسیار بسیار خوب و تمیز هستند. ChatGPT همچنان می‌تواند کمک کند، اما نسبت به Prisma به اندازهٔ Sequelize به‌روز نیست.
  • تا تاریخ ۱۵ مه ۲۰۲۳:
    • در NPM، Prisma آخرین‌بار «۶ روز پیش» به‌روزرسانی شده بود و ۱٬۳۴۴٬۷۰۵ دانلود هفتگی دارد.
    • در GitHub، Prisma آخرین‌بار «۳ ساعت پیش» به‌روزرسانی شده بود، 1.1k فورک و 31.3k ستاره دارد.

معایب:

  • از فیلتر Regex برای Postgres پشتیبانی نمی‌کند، اما گزینه‌های فیلتر «contains»، «includes» و «startsWith» را دارد.
  • بر اساس آزمایش‌های من، Prisma در ایجاد ورودی‌های مجموعه‌دادهٔ بزرگ ما در Postgres به‌طور قابل‌توجهی کندتر است. Sequelize آن ورودی‌های بزرگ را با نرخ حدود ۲.۲۶ ثانیه برای هر ورودی (فایل JSON) ایجاد کرد. در حالی که Prisma نرخ حدود ۱۱.۲۱ ثانیه برای هر ورودی (فایل JSON) داشت. بر اساس این نتایج، Prisma در این کار حدود ۵ برابر کندتر از Sequelize است.
  • همچنین، حذف یک ورودی از مجموعه‌دادهٔ بزرگ منجر به زمان انتظار نزدیک به ۴ دقیقه شد، که بسیار بسیار بد است.
  • Sequelize در حذف یک ورودی از بزرگ‌ترین و پیچیده‌ترین مجموعه‌داده در آزمایش‌های من خیلی سریع‌تر بود. Sequelize هنگام ساختار مجموعه‌داده، برتری‌ای نسبت به Prisma نداشت. هر دو باید با یک رابطهٔ سه‌لایهٔ تو‌در‌تو برای این مجموعه‌دادهٔ بزرگ کنار می‌آمدند، بنابراین می‌گویم مقایسه منصفانه‌ای بود.
  • Prisma یک استارتاپ است، به این معنی که Prisma یک شرکت انتفاعی با ۵۶.۵ میلیون دلار سرمایه‌گذاری است. با دانستن این موضوع، کُد/بستهٔ اصلی ORM پرایزما متن‌باز با مجوز Apache-2.0 است. این خوب است، اما از آنجا که Prisma سرمایه‌گذار دارد، اگر در مورد مجوزشان یک رفتار شبیه MongoDB داشته باشند، تعجب نمی‌کنم.

منابع