قاعدة بيانات Messenger (الجزء 1): نقوم بتصميم الإطار الأساسي

كيف يمكن ترجمة متطلبات العمل إلى هياكل بيانات محددة باستخدام مثال لتصميم قاعدة "من الصفر" للرسول؟



لن تكون قاعدة البيانات الخاصة بنا كبيرة وموزعة مثل قاعدة بيانات VKontakte أو Badoo ، ولكن "لتكون" ، لكنها جيدة - وظيفية وسريعة وتتناسب مع خادم PostgreSQL واحد - بحيث يمكنك نشر نسخة منفصلة من الخدمة في مكان ما على الجانب ، على سبيل المثال.

لذلك ، لن نتطرق إلى مشكلات التقاسم والتكرار والنظم الجغرافية الموزعة ، بل نركز على حلول الدوائر داخل قاعدة البيانات.

الخطوة 1: قليلا من خصوصية العمل


لن نقوم بتصميم مراسلاتنا في الملخص ، لكننا سنضمّنها في بيئة الشبكة الاجتماعية للشركات . بمعنى أن الأشخاص في مكاننا ليسوا "مجرد رسائل نصية" ، ولكن التواصل مع بعضهم البعض في سياق حل بعض مشكلات العمل.

وما هي تحديات الأعمال؟ .. دعونا نلقي نظرة على مثال فاسيلي ، رئيس قسم التطوير.
  • "نيكولاي ، هذا التصحيح يحتاج إلى هذا التصحيح اليوم!"
    لذلك ، يمكن إجراء المراسلات في سياق المستند .
  • "كوليا ، اذهب إلى DotA في المساء؟"
    أي أنه حتى مع وجود زوج واحد من المحاورين ، يمكن إجراء الاتصالات في نفس الوقت حول مواضيع مختلفة .
  • "بيتر ، نيكولاي ، انظر إلى ملحق السعر على الخادم الجديد."
    لذلك ، يمكن أن تحتوي رسالة واحدة على عدة مستلمين . في هذه الحالة ، قد تحتوي الرسالة على ملفات مرفقة .
  • "سيميون ، وأنت تبدو أيضًا."
    ويجب أن يكون من الممكن دعوة عضو جديد إلى المراسلات الحالية.

دعونا نتطرق إلى قائمة الاحتياجات "الواضحة" هذه.
بدون فهم التفاصيل المطبقة للمهمة والقيود التي تحددها ، من المستحيل عملياً تصميم مخطط قاعدة بيانات فعال لحلها.

الخطوة 2: الحد الأدنى من المنطق


حتى الآن ، يبدو كل شيء مشابهًا جدًا لمراسلات البريد الإلكتروني - وهي أداة أعمال تقليدية. لذا ، نعم ، "خوارزميًا" ، تتشابه العديد من مهام العمل مع بعضها البعض ، وبالتالي ستكون أدوات حلها متشابهة من الناحية الهيكلية.

دعونا إصلاح المخطط المنطقي الناتج عن العلاقات بين الكيانات. لسهولة فهم نموذجنا ، سنستخدم الخيار الأكثر بدائية لعرض نموذج ER دون تعقيدات تدوينات UML أو IDEF:



في مثالنا ، يكون الشخص والمستند و "النص" الثنائي للملف كيانات "خارجية" موجودة بشكل مستقل دون خدمتنا. لذلك ، سوف نعتبرهم ببساطة في المستقبل بعض الروابط "في مكان ما" بواسطة UUID.
ارسم المخططات بأكبر قدر ممكن - معظم أولئك الذين ستظهر لهم ليسوا خبراء في قراءة UML / IDEF. ولكن - تأكد من التعادل.

الخطوة 3: رسم هيكل الجدول


حول الجدول وأسماء الحقول
يمكن التعامل مع الأسماء "الروسية" للحقول والجداول بشكل مختلف ، ولكن هذه مسألة ذوق. نظرًا لعدم وجود مطورين أجانب في "Tensor" ، ويسمح لنا PostgreSQL بإعطاء أسماء حتى مع الحروف الهيروغليفية ، إذا كانت مرفقة بعلامات اقتباس ، فنحن نفضل تسمية الكائنات بشكل لا لبس فيه بوضوح ، حتى لا يكون هناك سوء فهم.

نظرًا لأن العديد من الأشخاص يكتبون الرسائل في وقت واحد ، يمكن للبعض منهم القيام بذلك في وضع عدم الاتصال ، فإن الخيار الأسهل هو استخدام UUIDs كمعرفات ليس فقط للكيانات الخارجية ، ولكن لجميع الكائنات داخل خدمتنا. علاوة على ذلك ، يمكن إنشاؤها حتى من جانب العميل - سيساعدنا ذلك في دعم إرسال الرسائل مع عدم إمكانية الوصول إلى قاعدة البيانات على المدى القصير ، واحتمال حدوث تصادم ضئيل للغاية.

سيبدو الهيكل التقريبي للجداول في قاعدة البيانات لدينا كما يلي:
الجداول: RU
CREATE TABLE ""( "" uuid PRIMARY KEY , "" uuid , "" text ); CREATE TABLE ""( "" uuid PRIMARY KEY , "" uuid , "" uuid , "" timestamp , "" text ); CREATE TABLE ""( "" uuid , "" uuid , PRIMARY KEY("", "") ); CREATE TABLE ""( "" uuid PRIMARY KEY , "" uuid , "BLOB" uuid , "" text ); 

الجداول: EN
 CREATE TABLE theme( theme uuid PRIMARY KEY , document uuid , title text ); CREATE TABLE message( message uuid PRIMARY KEY , theme uuid , author uuid , dt timestamp , body text ); CREATE TABLE message_addressee( message uuid , person uuid , PRIMARY KEY(message, person) ); CREATE TABLE message_file( file uuid PRIMARY KEY , message uuid , content uuid , filename text ); 

أسهل طريقة لوصف التنسيق هي البدء في "إزالة" الرسم البياني للروابط من الجداول التي لا تشير إلى أي شخص آخر.

الخطوة 4: اكتشاف متطلبات غير واضحة


هذا كل شيء ، لقد قمنا بتصميم قاعدة يمكنك من خلالها الكتابة والقراءة بطريقة أو بأخرى .

دعونا نضع أنفسنا في مكان مستخدم خدمتنا - ماذا نريد أن نفعل به؟

  • المشاركات الأخيرة
    هذا هو سجل لرسائل "بلدي" مرتبة زمنيا حسب الخصائص المختلفة. أين أنا واحد من المستلمين ، حيث أنا المؤلف ، حيث كتبوا إلي ، لكنني لم أرد ، حيث لم يردوا ...
  • المراسلات المشاركين
    من يشارك في هذه الدردشة الطويلة الطويلة؟

هيكلنا يتيح لنا حل كل من هذه المشاكل "بشكل عام" ، ولكن بسرعة - لا. تكمن المشكلة في أنه بالنسبة للفرز كجزء من المهمة الأولى ، من المستحيل إنشاء فهرس مناسب لكل من المشاركين (وسيكون عليك استرداد جميع السجلات) ، ولحل المشكلة الثانية ، تحتاج إلى استرداد جميع الرسائل المتعلقة بالموضوع.
يمكن لمهام المستخدم غير المتوقعة وضع حد للإنتاجية .

الخطوة 5: إزالة الصواب المعقول


ستساعد كلتا مشكلتنا في حل الجداول الإضافية ، حيث سنقوم بتكرار جزء من البيانات اللازمة لتشكيل فهارس مناسبة لمشاكلنا عليها.


الجداول: RU
 CREATE TABLE ""( "" uuid , "" smallint , "" timestamp , "" uuid , PRIMARY KEY("", "", "") ); CREATE INDEX ON ""("", "", "" DESC); CREATE TABLE ""( "" uuid , "" uuid , PRIMARY KEY("", "") ); 

الجداول: EN
 CREATE TABLE message_registry( owner uuid , registry smallint , dt timestamp , message uuid , PRIMARY KEY(owner, registry, message) ); CREATE INDEX ON message_registry(owner, registry, dt DESC); CREATE TABLE theme_participant( theme uuid , person uuid , PRIMARY KEY(theme, person) ); 

قمنا هنا بتطبيق طريقتين نموذجيتين تستخدم لإنشاء الجداول المساعدة:

  • سجلات الضرب
    نقوم بتكوين عدة سجلات مصدر دفعة واحدة من سجل مصدر واحد للرسالة إلى أنواع مختلفة من السجلات لأصحابها المختلفين - لكل من المرسل والمستلم. لكن كل سجل من السجلات يضع الآن على الفهرس - لأننا في الحالة النموذجية نريد أن نرى فقط الصفحة الأولى.
  • سجل فريد من نوعه
    في كل مرة ترسل فيها رسالة داخل موضوع معين ، يكفي التحقق من وجود مثل هذا الإدخال بالفعل. إذا لم يكن كذلك ، فأضفه إلى "قاموسنا".

في الجزء التالي من المقالة ، سنناقش تنفيذ التقسيم في بنية قاعدة البيانات الخاصة بنا.

Source: https://habr.com/ru/post/ar483176/


All Articles