سؤال

لدي مهمة تتمثل في تخزين كمية كبيرة من بيانات نظام تحديد المواقع العالمي (GPS) وبعض المعلومات الإضافية في قاعدة البيانات والوصول إليها لإعداد التقارير وبعض المهام الأخرى غير المتكررة.

عندما أتلقى رسالة من جهاز تحديد المواقع يمكن أن تحتوي على عدد متغير من الحقول.على سبيل المثال

الرسالة 1:دورة سرعة DeviceId Lat Lon DIO1 ADC1
الرسالة 2:معرف الجهاز اللات بالطبع DIO2 IsAlarmOn
الرسالة 3:دورة ارتفاع DeviceId Lat Lon DIO2 IsAlarmOn وما إلى ذلك.ما يصل إلى 20-30 الحقول

لا توجد طريقة لتوحيد عدد الحقول - بائعو الأجهزة المختلفون والبروتوكولات المختلفة وما إلى ذلك.والصداع الآخر هو حجم قاعدة البيانات وضرورة دعم أكبر عدد ممكن من بائعي قواعد البيانات (يتم استخدام NHibernate).

لذلك توصلت إلى فكرة تخزين الرسائل بهذه الطريقة:
الجدول 1 - المسارات
PK - معرف المسار
TrackStartTime
TrackEndTime
FirstMessageIndex (يخزن معرف الرسالة)
LastMessageIndex (يخزن معرف الرسالة)
معرف الجهاز (ليس FK)

الجدول 2 - الرسائل
PK - معرف الرسالة
الطابع الزمني
FirstDataIndex (يخزن DataId)
LastDataIndex (يخزن DataId)

الجدول 3 - بيانات الرسالة
PK - معرف البيانات
بيانات مزدوجة
نوع البيانات القصير

يتم تعيين كافة الفهارس مع hilo.قم بضبط استعلاماتي حتى يتمكن Nhibernate من التعامل مع رسائل incerting 3000+k بسرعة (يُستخدم الدمج أيضًا).أنا سعيد مع أجهزة الصراف الآلي برفومنس.لكنني لا أعرف كيف ستعمل بحجم 50+ جيجابايت أو 100+ جيجابايت.

سأكون ممتنًا جدًا لأية نصائح وتلميحات حول مشكلتي وتصميم التخزين بشكل عام=)
شكرا، أليكسي
ملاحظة: آسف لغتي الإنجليزية =)

هل كانت مفيدة؟

المحلول

باختصار، طلبك، على وجه التحديد بنية غير متجانسة من الرسائل المستلمة من أجهزة GPS، تدفع تصميمك نحو هيكل مخزن بيانات EAV (حيث يكون الكيان هو الرسالة، والسمة هي "MessageData.DataType" وتكون القيمة مزدوجة بشكل منهجي.)

تصميم الجداول الثلاثة الذي حددته في السؤال، يبدو أنه يخرج قليلاً عن تطبيق EAV التقليدي، بمعنى أن هناك تسلسل ضمني إلى الطريقة التي يتم بها تخزينMessageData حيث يتم ترقيم جميع نقاط البيانات لرسالة معينة بشكل تسلسلي (DataId)، وسيتم تشغيل الرابط من الرسالة إلى نقاط البيانات الخاصة بها بواسطة DataId ضمن نطاق.
هذه فكرة سيئة!العديد من المشاكل في ذلك، أحد أبرزها هو أن هذا يؤدي إلى اختناق غير ضروري لإدراج الرسائل، لا يمكن البدء في إدراج رسالة ثانية حتى يتم جميع نقاط البيانات الخاصة بالرسالة السابقة.هناك مشكلة أخرى وهي أنها تجعل من الصعب فهرسة العلاقة بين الرسالة ونقطة البيانات (لن يكون نظام إدارة قواعد البيانات الأساسي فعالاً في ذلك).
==> اقتراح:اعمل ال معرف الرسالة هو مفتاح خارجي في بيانات الرسالة طاولة.(وربما قم بإسقاط DataId PK في جدولMessageData تمامًا، فقط لتوفير المساحة، على حساب الاضطرار إلى استخدام مفتاح مركب للإشارة إلى سجل معين في هذا الجدول، على سبيل المثال لأغراض الصيانة)

اقتراح آخر هو أن تخزين السمات الأكثر شيوعًا (نقاط البيانات) على مستوى جدول الرسائل.على سبيل المثال، خطوط العرض والطول، ولكن ربما أيضًا الدورة التدريبية أو بعض التنبيهات وما إلى ذلك.السبب وراء وجود هذه المعلومات بشكل صحيح مع الرسالة هو تحسين الاستعلامات عن البيانات (الحد من عدد الصلات الذاتية اللازمة مع جدولMessageData.

نظرًا لأن كلا من جدولي الرسائل وMessageData قد لا يحتويان على جزء من الرسالة، فقد ترغب أيضًا في إعادة تسمية الجدول الأخير لـMessageDetail، أو بعض الأسماء المشابهة.

وأخيرا، قد تكون فكرة جيدة أن السماح بقيم بيانات أخرى غير تلك من النوع المزدوج.أتوقع أن تكون بعض التنبيهات مجرد منطقية، وما إلى ذلك.بصرف النظر عن السماح لك بقبول أنواع مختلفة من نقاط البيانات (على سبيل المثال، سلاسل رسائل الخطأ القصيرة...) فقد يمنحك هذا أيضًا الفرصة لتقسيم نقاط البيانات عبر جداول "تفصيلية" متعددة:واحد للزوجي، وواحد للقيم المنطقية، وواحد للسلاسل وما إلى ذلك.تؤدي طريقة العمل هذه إلى تعقيد المخطط، بمعنى أنك ستحتاج بعد ذلك إلى بناء بعض هذه التفاصيل في طريقة إنتاج الاستعلامات، ولكنها يمكن أن توفر بعض الإمكانات لتحقيق مكاسب في الأداء/التوسع.

نصائح أخرى

حاول أن تصف كيف يعمل الآن أكثر تفصيلًا في الإجابة ، لأن التعليقات ذات طول ثابت =) هنا هو استلام التسلسل:
1.تستقبل الخدمة الرسائل من MSMQ (يمكن أن يختلف عدد الرسائل - فهي تستخدم حزمة مجمعة مكونة من 500 رسالة).
2.ثم يقوم بتحسين معرفات الأجهزة المميزة.
3.لكل معرف جهاز يستخدم ذاكرة تخزين مؤقت معزولة لـ MS EntLib مع البنية:
معرف الجهاز --> قائمة حيث يكون معرف الجهاز هو مفتاح البحث.
4.إذا كان لدينا أكثر من ألف رسالة في ذاكرة التخزين المؤقت - فاكتبها في قاعدة البيانات في تسلسل واحد وبعد كتابة "الفهرس" في جدول البحث:
فِهرِس:بطاقة تعريف
معرف_تسلسلي
Index_start_datetime
Index_end_datetime
Index_first_dataid
Index_last_dataid
5.ينظف ذاكرة التخزين المؤقت لمعرف الجهاز هذا

أقوم أيضًا بتخزين البيانات في الأزواج:بيانات الهوية 1 نوع البيانات 2
على سبيل المثال Lat Lon ، دورة السرعة ، ADC1 ADC2 ، DIO1 ، DIO2 ، وإذا لم تكن هناك قيمة مقترنة:القيمة 0

اخترت مزدوجًا لأنه يمكنني تخزين كل أنواع البيانات التي ترسلها الأجهزة فيه.لا ترسل السلاسل، ولكن معظمها بنمط CSV مثل 1,0,23,50.0000N30.00000,1,2,12,0,1,2 وما إلى ذلك.حتى الإنذارات وغيرها لها نفس النوع من البيانات.عندما أحتاج إلى الحصول على بعض البيانات، أجد فقط فهارس لنافذة التاريخ والوقت المحددة ومعرف الجهاز وأحصل على البيانات الفعلية لمعرفة متى تبدأ وتنتهي.وليس هناك استعلامات معقدة.فقط 2 منها بسيطة.كود آخر يفسر هذا باستخدام بعض "تعيينات" البروتوكول.شكرا لنصيحة EAV.أعتقد أنه يناسب بشكل جيد.مسار الجدول الأول مخصص لتجميع الرسائل والحصول عليها بسرعة في خوارزمية الاسترجاع التي وصفتها بسلاسل مزدوجة من قبل.

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

بالإضافة إلى ذلك، يمكنك إنشاء حقول تحتوي على بيانات (طول) محددة، مما يعني أنه يمكنك حفظ المكان وتحسين الأداء.

لدي بائع واحد ذو قيم معروفة لذا قمت بإنشاء جدول واحد لهذا الغرض.يمكن تقسيم هذا الجدول بسهولة بواسطة آلية MS SQL Server الأصلية.

لذا، فإن أبسط موقف لدي يسمح لي بكتابة إجراء مخزن واحد لحفظ البيانات.لا يوجد NHibernate، فقط ICommand خالص.

بقية التطبيق يستخدم NHibernate.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top