MySQL أم Postgres لـ Laravel: الفروق التي تصل إلى شيفرتك
يخفي Eloquent أغلب المسافة بينهما، ثم لا تسافر معك حفنة من الخصائص. أيّها هي، وأيّها ستلاحظه بعد سنة.
يخفي Eloquent الفرق جيدًا بما يكفي ليختار أغلب الفرق بالعادة ولا يعرفوا أبدًا ماذا اختاروا. وذلك على ما يرام عادةً. ويكفّ عن كونه كذلك عند أربع نقاط محددة، وأربعتها تصل بعد القرار بوقت طويل.
أين هما متطابقان فعلًا
في كل ما تفعله أغلب التطبيقات. select وinsert والضمّ والمعاملات والفهارس
والمفاتيح الأجنبية وبنّاء الاستعلامات وبنّاء المخطط والهجرات والمصانع وكل نوع
علاقة في Eloquent. إن كان التطبيق CRUD على مخطط علائقي، فلن تشعر بفرق مدة
طويلة.
فالصياغة الصادقة ليست "أيّهما أفضل"، بل: أي الانحرافات الأربعة أدناه سيبلغه تطبيقك فعلًا.
١. JSON، حيث يتقدّم Postgres وحيث يهم ذلك
كلاهما يخزّن JSON. وواحد فقط يفهرس مسارات اعتباطية داخله جيدًا.
$table->json('settings');على Postgres تريد jsonb لا json، ودالة jsonb() في Laravel تعطيك إياه.
والفرق أن jsonb يُحلَّل ويُخزَّن بصورة ثنائية يستطيع فهرس GIN تغطيتها، فاستعلام
كهذا يستخدم فهرسًا:
Order::where('meta->channel', 'marketplace')->get();وعلى MySQL يوصلك عمود مولَّد مع فهرس عليه إلى المكان نفسه لمسار واحد معروف، وهو جيد حين يكون لديك مسار واحد معروف ومرهق حين تكون الهيئة ديناميكية فعلًا.
إن كان التطبيق يخزّن كتلة إعدادات لكل مستأجر، أو حمولة لكل webhook، أو أي شيء ستريد لاحقًا الترشيح به دون أن تعرف اليوم بأي مفتاح - فتلك أقوى حجة منفردة لصالح Postgres في تطبيق Laravel.
٢. حساسية حالة الأحرف، وهي فخ سلوكي
الترتيب الافتراضي في MySQL لا يميّز بين الكبيرة والصغيرة. وPostgres يميّز.
User::where('email', 'Test@example.com')->first();هذا يجد test@example.com على MySQL ولا يجد شيئًا على Postgres. وكل تطبيق
كُتب مقابل MySQL فيه عدد من المقارنات لا تعمل إلا بسبب ذلك الافتراض، ولم يكتب
أحد أيّها.
لا أحد السلوكين خاطئ. الخطأ اكتشاف الفرق أثناء ترحيل. طبّع عند الكتابة - حوّل البريد إلى أحرف صغيرة في mutator، وأضف فهرسًا فريدًا على العمود المطبَّع - ويكفّ السؤال عن الأهمية في أي المحركين.
وينطبق الأمر نفسه على الترتيب. الأمر ORDER BY name يضع apple وApple
بشكل مختلف في الاثنين، وهو ما يظهر في القوائم المقسّمة كسجلات تظهر في صفحتين أو
لا تظهر في أي منهما.
٣. قيود وأنواع يملكها Postgres ولا يملكها MySQL
قيود التحقق التي تتحقق فعلًا. عمود حالة محصور في أربع قيم، تفرضه قاعدة البيانات بدل طلب نموذج تستطيع مهمة في طابور تجاوزه.
الفهارس الجزئية. فهرس على الصفوف المهمة وحدها - WHERE deleted_at IS NULL
على جدول ذي حذف ناعم، أو على الاشتراكات النشطة فقط. على جدول كبير بمجموعة
فرعية ساخنة صغيرة هذا مكسب كبير، ولا مكافئ له في MySQL.
أنواع مصفوفات ومدى حقيقية، وامتدادات. وإن كان لديك أي شيء جغرافي، فـ PostGIS هو سبب كون القرار قد اتُّخذ سلفًا.
INSERT ... RETURNING، الذي يتيحه Laravel ويعني أن إدراجًا يحتاج الصف
المولَّد مرتجعًا هو رحلة واحدة بدل اثنتين.
٤. الفروق التشغيلية، وهي التي توقظك
تغييرات المخطط. كلاهما قد يقفل. يضيف Postgres عمودًا قابلًا للإفراغ فورًا
ويبني فهرسًا بـ CONCURRENTLY - وهو ما لا يصدره Laravel، فتكتبه يدويًا، ولا
يعمل داخل معاملة. وMySQL الحديث يضيف الأعمدة فورًا في كثير من الحالات ويملك
تغيير بنية على الخط في كثير غيرها. ولا أحدهما آمن افتراضيًا على جدول كبير،
ونمط الفشل متطابق.
النسخ المتماثل والاتصالات. اتصالات Postgres أغلى، ولهذا يبلغ تطبيق Laravel بأسطول عمّال كبير حدّ الاتصالات أسرع، ولهذا يظهر أمامه pooler أبكر. وMySQL يحتمل عددًا خامًا أعلى من الاتصالات. وهذا يتفاعل مباشرةً مع عدد عمّال الطوابير الذين تشغّلهم.
البحث بالنص الكامل. لدى Postgres بحث نص كامل مدمج وقابل للاستخدام مع ترتيب. وما لدى MySQL أضعف. وكلاهما حلّ مؤقت قبل محرك بحث حقيقي، لكن الحلّ المؤقت يدوم أطول على Postgres.
كيف تختار فعلًا
اختر Postgres إن كان نموذج البيانات فيه JSON ستستعلم عنه، أو قيود تريدها مفروضة لا موثوقًا بها، أو أي شيء جغرافي، أو تقارير ستريد قريبًا دوال نوافذ وتعبيرات جدولية مشتركة.
اختر MySQL إن كان فريقك واستضافتك يشغّلانه بالفعل والتطبيق عمل علائقي مباشر. الألفة عند من سيُستدعون الثالثة فجرًا مُدخَل هندسي حقيقي لا تنازل.
وأيّهما اخترت، ثبّته في كل مكان. أغلى نسخة من هذا القرار فريقٌ يطوّر على SQLite ويختبر على MySQL ويشغّل Postgres في الإنتاج، فيكتشف الفروق حادثًا تلو آخر. بيئتك المحلية وتكاملك المستمر وقاعدة بيانات إنتاجك ينبغي أن تكون المحرك نفسه والإصدار الرئيسي نفسه - لأسباب تظهر في مجموعة الاختبارات أيضًا.
