it-swarm.asia

كيفية تصميم قاعدة بيانات لتخزين قائمة مرتبة؟

إنني أتطلع إلى تخزين قائمة مرتبة داخل قاعدة بيانات. أريد تنفيذ العمليات التالية بكفاءة.

  1. إدراج (س) - إدراج سجل س في الجدول
  2. حذف (x) - حذف سجل x من الجدول
  3. قبل (س ، ن) - إرجاع السجلات "ن" التي تسبق السجل س في القائمة المصنفة.
  4. بعد (x، n) - قم بإرجاع السجلات 'n' التي تلي السجل x في القائمة التي تم فرزها.
  5. First (n) - إرجاع أول سجلات "n" من القائمة التي تم فرزها.
  6. الأخير (ن) - إرجاع آخر تسجيلات "ن" من القائمة التي تم فرزها.
  7. قارن (س ، ص) - بالنظر إلى سجلين س وص ص من الجدول ، ابحث عما إذا كان س> ص.

الطريقة البسيطة التي يمكن أن أفكر بها هي تخزين نوع من سمة "رتبة" في الجدول والاستعلام عن طريق الفرز على تلك السمة. ولكن في هذه الطريقة يصبح إدراج/تعديل سجل برتبة عملية مكلفة. هل هناك طريقة أفضل؟

على وجه التحديد ، أتطلع إلى تنفيذ الجدول باستخدام SimpleDB من Amazon. ولكن يجب أن تكون الإجابة العامة لقاعدة بيانات علائقية مفيدة أيضًا.

تحديث ملف تعريف التحميل:

نظرًا لأنني أخطط لهذا لتطبيق ويب ، فإنه يعتمد على عدد المستخدمين الذين يستخدمون التطبيق.

إذا كان هناك 100 ألف مستخدم نشط (تفاؤل فائق: P) ، فعندئذ سيكون تقديري التقريبي جدًا في اليوم

500 ألف يختار ، 100 ألف إدراج وحذف ، 500 ألف تحديث

أتوقع أن ينمو الجدول إلى 500 ألف في المجموع.

إنني أتطلع إلى تحسين التحديثات وإدراجها ومقارنة العمليات. سيتم تغيير ترتيب العناصر باستمرار وأحتاج إلى إبقاء الجدول محدثًا.

44
chitti

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

إذا كانت هي خاصية عشوائية لبياناتك ، فيجب تخزينها كعمود في جدول السجلات. بافتراض أن SimpleDB في Amazon يشبه نظام RDBMS النموذجي ، يمكنك بعد ذلك فهرسة هذا العمود وتلبية جميع استفساراتك أعلاه بسرعة باستخدام استراتيجية الفهرسة المناسبة. يعد هذا أمرًا طبيعيًا بالنسبة لنظام RDBMS.

نظرًا لأنك تتوقع نشاطًا عاليًا في الإدراج والتحديث ، ولكن أيضًا نشاط قراءة مرتفع نسبيًا ، أوصي بإجراء ما يلي:

  • قم بتجميع الجدول في الترتيب ، خاصة إذا كانت الغالبية العظمى من استفساراتك ضد الترتيب. إذا لم يكن الأمر كذلك ، أو إذا لم يكن اختيار مفتاح التجميع متاحًا في SimpleDB ، فقم فقط بإنشاء فهرس بترتيب كعمود بادئة. وهذا من شأنه إرضاء الاستفسارات 3-6.
  • الفهرس الموجود على السجل أولاً ثم الترتيب (أو ، في عالم SQL Server ، قم فقط بالتسجيل و INCLUDE- الترتيب ، أو قم بالتسجيل فقط إذا كنت قد جمعت في الترتيب) سوف يلبي الاستعلام 7.
  • يمكن تحسين العمليات 1 و 2 من خلال تباعد البيانات بشكل مناسب (أي تعيين FILLFACTOR في SQL Server). هذا مهم بشكل خاص إذا كنت تتجمع في الرتبة.
  • أثناء إدراج أو تحديث الرتب ، حافظ على أكبر قدر ممكن من الفجوة بين أرقام الرتب لتقليل هذا الاحتمال أنك ستحتاج إلى إعادة ترتيب سجل موجود ليلائم إدراج الرتبة أو التحديث. على سبيل المثال ، إذا قمت بتصنيف سجلاتك في خطوات 1000 ، فإنك تترك مساحة كافية لنصف ذلك العديد من التغييرات والإدخالات بأقل فرصة ، ستحتاج إلى إعادة ترتيب سجل غير مشارك بشكل مباشر في تلك التغييرات.
  • في كل ليلة ، أعد ترتيب جميع السجلات لإعادة تعيين فجوات الترتيب بينهما.
  • يمكنك ضبط عدد مرات إعادة الترتيب الشامل وكذلك حجم فجوة التصنيف لتلائم العدد المتوقع للإدخالات أو التحديثات المتعلقة بعدد السجلات الموجودة. لذلك إذا كان لديك 100 ألف سجل وتتوقع أن تكون إدخالاتك وتحديثاتك 10٪ من ذلك ، اترك مساحة كافية لـ 10 آلاف من الرتب الجديدة وأعد ترتيبها كل ليلة.
  • إن إعادة ترتيب 500 ألف سجل عملية مكلفة ، ولكن القيام بها مرة واحدة يوميًا أو أسبوعيًا خارج ساعات العمل يجب أن يكون جيدًا لقاعدة بيانات كهذه. هذا الترتيب الشامل خارج ساعات العمل للحفاظ على فجوات الترتيب هو ما يوفر عليك إعادة ترتيب العديد من السجلات لكل تحديث رتبة أو إدراج خلال ساعات الذروة العادية.

إذا كنت تتوقع قراءة 100K + على جدول بحجم 100K + ، فلا أوصي باستخدام نهج القائمة المرتبطة. لن يتم قياسها جيدًا لتلك الأحجام.

22
Nick Chammas

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

قد يكون النهج البديل هو نمذجة السجلات كقائمة مرتبطة باستخدام عمود مفتاح انعكاسي خارجي "سابق" على الجدول:

ID   setID   item       predecessor
---  ------  ------     ------------
1    1       Apple      null
2    1       Orange     1
3    2       Cucumber   null
4    1       Pear       2
5    1       Grape      4
6    2       Carrot     3

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

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

13
bpanulla

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

6
Joel Brown

هذه هي قيود غير RDBMS مثل simpleDB. لا يمكن تنفيذ الميزات التي تطلبها على جانب DB في simpleDB ، يجب تنفيذها من جانب البرمجة/التطبيق.

لنظام إدارة قواعد البيانات الديناميكية مثل SQL server ، الميزات التي تحتاجها بدائية للفهرس العنقودي.

  • إدراج (x) - إدراج سجل x في الجدول> إدراج بسيط.
  • حذف (x) - حذف سجل x من الجدول> حذف بسيط.
  • قبل (س ، ن) - إرجاع السجلات "ن" التي تسبق السجل س في القائمة المصنفة. > حدد أهم النتائج n حيث x أقل من القيمة وترتيبها حسب البند.

  • بعد (x، n) - قم بإرجاع السجلات 'n' التي تلي السجل x في القائمة التي تم فرزها. > حدد أهم النتائج n حيث x أكبر من القيمة وترتيبها حسب البند.

  • First (n) - إرجاع أول سجلات "n" من القائمة التي تم فرزها. > حدد أهم النتائج n.

  • الأخير (ن) - إرجاع آخر تسجيلات "ن" من القائمة التي تم فرزها. > حدد أهم نتائج n بعد الترتيب حسب التفاصيل.

  • قارن (س ، ص) - بالنظر إلى سجلين س وص ص من الجدول ، ابحث عما إذا كان س> ص. > بيان TSQL IF.
1
StanleyJohns

إليك ما اعتدت عليه إعادة ترتيب جدول Postgres بعد كل إدخال:

CREATE OR REPLACE FUNCTION re_rank_list() RETURNS trigger AS $re_rank_list$
DECLARE
    temprow record;
    row_idx integer := 1;    
BEGIN
    FOR temprow IN
    SELECT * FROM your_schema.your_list WHERE list_id = NEW.list_id ORDER BY rank ASC
    LOOP
        UPDATE your_schema.your_list SET rank = row_idx * 100 WHERE id = temprow.id;
        row_idx := row_idx + 1;
    END LOOP;
    RETURN NEW;
END;
$re_rank_list$ LANGUAGE plpgsql;


CREATE TRIGGER re_rank_list AFTER UPDATE ON your_schema.your_list_value
    FOR EACH ROW 
    WHEN (pg_trigger_depth() = 0)
    EXECUTE PROCEDURE re_rank_list();

بالنسبة لحالة الاستخدام الخاصة بي ، فإن الأداء ليس مصدر قلق ، ولكن الثقة في أنه لن ينكسر أو يتصرف بشكل غريب أمر مهم.

0
Mark