سؤال

لدي جدول قاعدة بيانات يحتوي كل صف فيه على مفتاح أساسي ورسالة ومستخدم تم إنشاؤه عشوائيًا.كل مستخدم لديه حوالي 10-100 رسالة ولكن هناك 10-50 ألف مستخدم.

أكتب الرسائل يوميًا لكل مستخدم دفعة واحدة.أريد التخلص من الرسائل القديمة لكل مستخدم قبل كتابة الرسائل الجديدة لإبقاء الجدول صغيرًا قدر الإمكان.

الآن أفعل هذا بفعالية:

delete from table where user='mk'

ثم اكتب كافة الرسائل لهذا المستخدم.أرى الكثير من الخلاف لأن لدي الكثير من المواضيع التي تفعل ذلك في نفس الوقت.

لدي مطلب إضافي للاحتفاظ بأحدث مجموعة من الرسائل لكل مستخدم.

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

يمكن لأي شخص أن يقدم أي نصيحة؟

هل سيكون من الأفضل أن:

select key from table where user='mk'

ثم حذف الصفوف الفردية من هناك؟أعتقد أن هذا قد يؤدي إلى قفل أقل وحشية.

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

المحلول

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

(بالطبع، لا يمكن أن يكون اسم العمود مستخدمًا في قاعدة بيانات Oracle، نظرًا لأنه كلمة محجوزة!)

يحرر: لقد قلت أن العمود USER غير مفهرس.وهذا يعني أن كل عملية حذف ستتضمن فحصًا كاملاً للجدول يصل إلى 50 ألف*100 = 5 ملايين صف (أو في أفضل الأحوال 10 ألف * 10 = 100000 صف) لحذف 10-100 صف فقط.قد تؤدي إضافة فهرس على USER إلى حل مشكلاتك.

نصائح أخرى

إذا كنت تفعل ذلك كل يوم لكل مستخدم، فلماذا لا تحذف كل سجل من الجدول في عبارة واحدة؟او حتى

truncate table whatever reuse storage
/

يحرر

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

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

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

وأعتقد أنك بحاجة لتحديد الاحتياجات الخاصة بك أكثر وضوحا قليلا ...

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

وDELETE * FROM الرسائل INNER JOIN TEMP_MEMBERS ON ID = TEMP_ID

وINSERT INTO الرسائل SELECT * FROM TEMP_messges

وايم لم تكن مألوفة مع تركيب وأوراكل، ولكن هذه هي الطريقة التي أود أن الاقتراب منه IF الرسائل للمستخدمين تتم جميع في تعاقب سريع.

ويساعد هذا الأمل

تحدث إلى DBA الخاص بك

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

بمجرد إلقاء نظرة سريعة على بيان مشكلتك، لا يبدو أنك ستنظر في مشكلات الخلاف، لكنني لا أعرف أي شيء عن بنيتك الأساسية.

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

وهذا قد تسريع الامور:

وإنشاء جدول البحث:

create table rowid_table (row_id ROWID ,user VARCHAR2(100));
create index rowid_table_ix1 on rowid_table (user);

وتشغيل وظيفة ليلا:

truncate table rowid_table;
insert /*+ append */ into rowid_table
select ROWID row_id , user
from table;
dbms_stats.gather_table_stats('SCHEMAOWNER','ROWID_TABLE');

وبعد ذلك عند حذف السجلات:

delete from table
where ROWID IN (select row_id
                from rowid_table
                where user = 'mk');

اقتراحك الخاص يبدو معقولا جدا.القفل على دفعات صغيرة له ميزتان:

  • المعاملات ستكون أصغر
  • سيقتصر القفل على بضعة صفوف فقط في المرة الواحدة

يجب أن يكون تأمين الدفعات بمثابة تحسن كبير.

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