تخطَّ إلى المحتوى

Prisma أم Drizzle: الاختيار يدور حول أين يعيش المخطط

أحدهما يولّد عميلًا من ملف مخطط يملكه؛ والآخر SQL بأنواع تكتبه أنت. والقرار يتعلق بالصياغة أقل مما يتعلق بمن يملك قاعدة بياناتك.

4 دقيقة قراءة

كلاهما جيد. فرق تسلّم تطبيقات جادّة بكل منهما، والجدال بينهما على الإنترنت أعلى صوتًا من الفرق في النتيجة.

وما يختلف فعلًا سؤال ينبغي أن تجيب عنه على أي حال: هل المخطط ملف في مستودعك تُولَّد منه قاعدة البيانات، أم أن قاعدة البيانات هي الحقيقة وشيفرتك رؤية بأنواع عليها؟

Prisma: ملف المخطط هو مصدر الحقيقة

تكتب schema.prisma، ويعطيك عميل مولَّد واجهة بأنواع.

model Order {
  id        String   @id @default(cuid())
  total     Int
  customer  Customer @relation(fields: [customerId], references: [id])
  customerId String
  createdAt DateTime @default(now())
}
const orders = await db.order.findMany({
  where: { total: { gt: 5000 } },
  include: { customer: true },
  take: 20,
});

فيمَ هو جيد. ملف واحد يصف النموذج كله، والعلاقات صريحة فيه. والعميل مريح وقابل للاستكشاف ويصعب إساءة استخدامه. والهجرات تُولَّد من الفرق بين المخطط وقاعدة البيانات، ما يزيل فئة كاملة من الأخطاء المكتوبة يدويًا. ولفريق لا يتقن SQL، ذلك فرق إنتاجية كبير وهو السبب الصادق لشعبيته.

أين يكلّفك. العميل المولَّد أثر حقيقي - يجب توليده في البناء، وهو ليس صغيرًا، ما يظهر في حزمة بلا خوادم وفي البدء البارد. والتجريد شامل بما يكفي ليشعر النزول تحته، حين تحتاج استعلامًا لا تعبّر عنه الواجهة، وكأنه مغادرة للأداة لا استخدام لها.

Drizzle: المخطط TypeScript والاستعلامات SQL

تصف الجداول بـ TypeScript، وبنّاء الاستعلامات قريب من SQL بما يكفي ليعلّمك قراءتُه الاستعلام.

export const orders = pgTable('orders', {
  id: text('id').primaryKey(),
  total: integer('total').notNull(),
  customerId: text('customer_id').notNull().references(() => customers.id),
  createdAt: timestamp('created_at').defaultNow(),
});
 
const rows = await db
  .select()
  .from(orders)
  .where(gt(orders.total, 5000))
  .limit(20);

فيمَ هو جيد. إنه رفيع. لا عميل مولَّد ولا محرك وقت تشغيل، فالحزمة صغيرة والبدء البارد أفضل - وهي الحجة التي تهم على منصة تحمل فيها كل دالة اعتمادياتها. ولأن بنّاء الاستعلامات ينعكس على SQL، يُكتب الاستعلام المعقّد بالأداة نفسها التي يُكتب بها البسيط بدل فتحة هروب.

أين يكلّفك. عليك أن تعرف SQL، وراحة التعامل مع العلاقات عمل أكثر من include. وتوليد الهجرات موجود وأقل رأيًا. ولفريق يفضّل التفكير بالكائنات على التفكير بالضمّ، فيه احتكاك أكبر لكل استعلام.

السؤال الذي يقرره

ليس الصياغة. اسأل من يملك المخطط.

إن كان يملكه التطبيق - أرض جديدة، فريق واحد، وقاعدة البيانات موجودة لخدمة هذه الشيفرة - فملف مخطط يولّد قاعدة البيانات ترتيب نظيف، ونموذج Prisma يناسبه تمامًا.

وإن كانت تملكه قاعدة البيانات - أقدم من التطبيق، وأنظمة أخرى تكتب فيها، ولمدير قواعد البيانات آراء، وفيها views ومحفّزات وأشياء لم ينشئها ORM لديك - فأداة تصف ما هو موجود تناسب أكثر من أداة تريد تعريفه.

والحالة الثانية أشيع مما توحي به كتابات الأرض الجديدة، وفيها يبدأ ORM قائم على المخطط في الشعور بأنه يقاومك.

الجزء الخاص بـ Next.js

أمران يهمّان هنا ولم يكونا ليهمّا على خادم طويل العمر.

الحزمة والبدء البارد. العميل الأثقل في كل نسخة دالة يُدفع ثمنه عند كل بدء بارد. تلك نقطة حقيقية لصالح الخيار الأرفع، وهي أصغر من استعلام واحد سيئ الشكل. قِس مسارك أنت قبل أن تعدّها حاسمة.

أين يُنشأ العميل. متطابق للاثنين وأهم من الاختيار: نسخة لكل نطاق وحدة، لا لكل طلب. أخطئ في ذلك مع أيّهما وستكون تقرأ عن حدود الاتصالات لا عن أنظمة ORM.

وإن كنت تنشر على بيئة الحافة، افحص مسار المشغّل لا الـ ORM - كلاهما يعمل هناك عبر مشغّل قادر على HTTP، وكلاهما لا يعمل عبر مشغّل TCP.

ما الذي يسوء فعلًا، مع أيّهما

ليس الـ ORM أبدًا. في كل شيفرة سُلّمت إلينا، كانت مشكلات طبقة البيانات القائمة القصيرة نفسها: استعلام داخل حلقة، وصفحة تجلب البيانات نفسها في ثلاثة مكوّنات لأن أحدًا لم يزل التكرار، ولا فهرس خلف مرشِّح يتحكم به مستخدم، وعميل يُنشأ لكل طلب.

الأربعة ممكنة في الأداتين وغير مرئية في الأداتين. أيًّا اخترت، فما يستحق إضافته في الأسبوع الأول هو وسيلة لرؤية عدد استعلامات مسار - لأن ذلك الرقم هو ما ستصحّحه فعلًا، ولا يغيّره أي من الاختيارين.

أسئلة ذات صلة

أيّهما أسرع؟
على المستوى الذي يهم، الاستعلام هو الاستعلام، وكلاهما يرسل SQL متشابهًا لعمل متشابه. وحيث يختلفان هو ما حوله - وزن الحزمة، والبدء البارد، وكم من آلة التشغيل تجلس بين استدعائك والسلك. وذلك الفرق حقيقي في دالة بلا خوادم وقريب من عديم الأهمية على خادم طويل العمر.
هل يمكن الانتقال من أحدهما إلى الآخر؟
نعم، والكلفة تتناسب مع كم من شيفرتك يلمس العميل مباشرةً. كلاهما يقرأ الجداول نفسها، فيمكنهما التعايش أثناء انتقال - وهي الطريقة العاقلة، وحدةً وحدة، بدل فرع يعيد كتابة كل استعلام دفعة واحدة.
وماذا عن قاعدة البيانات الموجودة أصلًا؟
كلاهما يستطيع استبطان مخطط قائم والتوليد منه. وتلك طريقة جيدة للبدء بأيّهما، ويستحق فعلها قبل الالتزام - فالنموذج الذي تنتجه الأداة من جداولك الحقيقية يخبرك عن الملاءمة أكثر من أي مثال في التوثيق.
هل نحتاج ORM أصلًا؟
لا تحتاج، وتطبيق صغير بحفنة استعلامات تخدمه جيدًا دالة استعلام بأنواع مع المشغّل. وما تفقده هو الهجرات والرابط بين المخطط والأنواع، وهما بالضبط ما تبدأ في افتقاده عند النقطة التي يكفّ فيها التطبيق عن كونه صغيرًا.

← العودة إلى كل المقالات

اتصل بنا+1 848 272 7583واتساب+90 850 308 5436البريدinfo@codefacture.comصفحة التواصل