سؤال

لدينا استعلام لإزالة بعض الصفوف من الجدول بناء على حقل معرف (المفتاح الأساسي). إنه استعلام مباشر للغاية:

delete all from OUR_TABLE where ID in (123, 345, ...)

المشكلة هي رقم المشكلات يمكن أن تكون ضخمة (على سبيل المثال 70k)، لذلك يستغرق الاستعلام وقتا طويلا. هل هناك أي طريقة لتحسين هذا؟ (نحن نستخدم Sybase - إذا كان هذا يهم).

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

المحلول

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

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

ولكن في أي حال، أود أن أضع قيمي الرئيسية التي أنوي حذفها في جدول مؤقت وحذف من هناك.

نصائح أخرى

هناك طريقتان لإجراء تصريحات مثل هذا أداء:

  1. قم بإنشاء جدول جديد ونسخ كل الصفوف للحذف. مبادلة الجداول بعد ذلك (alter table name ...) أقترح أن أعطيه محاولة حتى عندما يبدو غبيا. بعض قواعد البيانات أسرع بكثير في النسخ من الحذف.

  2. تقسيم الجداول الخاصة بك. قم بإنشاء جداول N واستخدم طريقة عرض للانضمام إليها في واحدة. فرز الصفوف إلى جداول مختلفة تم تجميعها بواسطة معيار الحذف. الفكرة هي إسقاط طاولة كاملة بدلا من حذف الصفوف الفردية.

أنا أتساءل عما إذا كان تحليل البند مع العناصر 70k في هذه المشكلة. هل جربت طاولة مؤقت مع انضمامها بدلا من ذلك؟

هل يمكن أن يعالج Sybase حجج 70k في جملة؟ جميع قواعد البيانات التي عملت بها مع بعض الحد من عدد الحجج IN بند. على سبيل المثال، حد على أوراكل حوالي 1000.

يمكنك إنشاء subselect بدلا من البند؟ سوف تقصر SQL. ربما يمكن أن يساعد ذلك في مثل هذا العدد الكبير من القيم في البند. شيء من هذا القبيل:

  DELETE FROM OUR_TABLE WHERE ID IN 
        (SELECT ID FROM somewhere WHERE some_condition)

يمكن استلام حذف عدد كبير من السجلات مع بعض التدخلات في قاعدة البيانات، إذا سمح نموذج قاعدة البيانات. فيما يلي بعض الاستراتيجيات:

  1. يمكنك تسريع الأمور عن طريق إسقاط الفهارس وحذف السجلات ومؤشرات إعادة إنشائها مرة أخرى. سيؤدي ذلك إلى إلغاء أشجار مؤشر Rebalancing أثناء حذف السجلات.

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

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

أود أن أحاول مزيجا من 1 و 2 و 3. إذا كان هذا لا يعمل، ثم 4. إذا كان كل شيء بطيئا، فسأبحث عن مربع أكبر - المزيد من الذاكرة وأقراص أسرع.

تعرف على ما يستخدم الأداء!

في العديد من الحالات، قد تستخدم إحدى الحلول المقدمة. ولكن قد يكون هناك آخرون (بناء على المعرفة Oracle، لذلك ستظل الأمور مختلفة على قواعد البيانات الأخرى. تحرير: رأيت للتو أنك ذكرت Sybase):

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

ولكن تذكر: اكتشف ما يستخدم الأداء أولا.

عند استخدام بيانات DDL تأكد من أنك تفهم وقبول العواقب التي قد يكون لها على المعاملات والنسخ الاحتياطية.

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

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

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

أعتقد أيضا أن جدول TEMP من المحتمل أن يكون أفضل حل.

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

لذلك، بالنظر إلى جدول المثال هذا:

    -- set up tables for this example
    if exists (select id from sysobjects where name = 'OurTable' and type = 'U')
        drop table OurTable
    go

    create table OurTable (ID integer primary key not null)
    go
    insert into OurTable (ID) values (1)
    insert into OurTable (ID) values (2)
    insert into OurTable (ID) values (3)
    insert into OurTable (ID) values (4)
    go

يمكننا بعد ذلك كتابة رمز حذف الخاص بنا على النحو التالي:

    create table #IDsToDelete (ID integer not null)
    go
    insert into #IDsToDelete (ID) values (2)
    insert into #IDsToDelete (ID) values (3)
    go
    -- ... etc ...
    -- Now do the delete - notice that we aren't using 'from'
    -- in the usual place for this delete
    delete OurTable from #IDsToDelete
       where OurTable.ID = #IDsToDelete.ID
    go
    drop table #IDsToDelete
    go
    -- This returns only items 1 and 4
    select * from OurTable order by ID
    go

هل لدينا_ لا يمكن مرجعا على حذف cascade؟

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