أسرع طريقة لحذف كافة البيانات في جدول كبير

StackOverflow https://stackoverflow.com/questions/64117

  •  09-06-2019
  •  | 
  •  

سؤال

اضطررت إلى حذف جميع الصفوف من جدول السجل الذي يحتوي على حوالي 5 ملايين صف.كانت محاولتي الأولية هي إصدار الأمر التالي في محلل الاستعلام:

حذف منclient_log

الذي استغرق وقتا طويلا جدا.

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

المحلول

الدفع اقتطاع الجدول وهو أسرع بكثير.

نصائح أخرى

لقد اكتشفت اقتطاع الجدول في مرجع MSDN Transact-SQL.ولجميع المهتمين إليكم الملاحظات:

TRUNCATE TABLE مطابق وظيفيًا لعبارة DELETE بدون عبارة WHERE:كلاهما يزيل كافة الصفوف في الجدول.لكن TRUNCATE TABLE أسرع ويستخدم موارد سجل النظام والمعاملات أقل من DELETE.

تقوم عبارة DELETE بإزالة الصفوف واحدًا تلو الآخر وتسجل إدخالاً في سجل المعاملات لكل صف محذوف.يقوم TRUNCATE TABLE بإزالة البيانات عن طريق إلغاء تخصيص صفحات البيانات المستخدمة لتخزين بيانات الجدول، ويتم تسجيل عمليات إلغاء تخصيص الصفحات فقط في سجل المعاملات.

يقوم TRUNCATE TABLE بإزالة كافة الصفوف من الجدول، ولكن تبقى بنية الجدول وأعمدته وقيوده وفهارسه وما إلى ذلك.تتم إعادة تعيين العداد المستخدم بواسطة هوية للصفوف الجديدة إلى بذرة العمود.إذا كنت تريد الاحتفاظ بعداد الهوية، استخدم DELETE بدلاً من ذلك.إذا كنت تريد إزالة تعريف الجدول وبياناته، فاستخدم عبارة DROP TABLE.

لا يمكنك استخدام TRUNCATE TABLE على جدول تمت الإشارة إليه بواسطة قيد FOREIGN KEY؛بدلاً من ذلك، استخدم عبارة DELETE بدون جملة WHERE.نظرًا لعدم تسجيل TRUNCATE TABLE، لا يمكن تنشيط المشغل.

لا يجوز استخدام TRUNCATE TABLE على الجداول المشاركة في طريقة عرض مفهرسة.

هناك أسطورة شائعة مفادها أن TRUNCATE يتخطى سجل المعاملات بطريقة ما.

هذا سوء فهم، وهو مذكور بوضوح في MSDN.

تم استدعاء هذه الأسطورة في العديد من التعليقات هنا.فلنقضي عليه معاً ;)

كمرجع اقتطاع الجدول يعمل أيضًا على MySQL

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

أستخدم الطريقة التالية للتخلص من الجداول، مع المكافأة الإضافية التي تترك لي نسخة أرشيفية من الجدول.

CREATE TABLE `new_table` LIKE `table`;
RENAME TABLE `table` TO `old_table`, `new_table` TO `table`;

truncate table يكون لا منصة SQL مستقلة.إذا كنت تشك في أنك قد من أي وقت مضى تغيير موفري قاعدة البيانات، قد تكون حذرا من استخدامه.

على SQL Server، يمكنك استخدام Truncate Table وهو أمر أسرع من الحذف العادي ويستخدم أيضًا موارد أقل.سيتم إعادة تعيين أي حقول هوية إلى القيمة الأولية أيضًا.

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

لاحظ أن TRUNCATE سيقوم أيضًا بإعادة تعيين أي مفاتيح متزايدة تلقائيًا، إذا كنت تستخدمها.

إذا كنت لا ترغب في فقدان مفاتيح الزيادة التلقائية، فيمكنك تسريع عملية الحذف عن طريق الحذف في مجموعات (على سبيل المثال، DELETE FROM table WHERE id > 1 AND id < 10000).سيؤدي ذلك إلى تسريع العملية بشكل كبير وفي بعض الحالات منع قفل البيانات.

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

اقتطاع جدول Client_log

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

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

أنت تستخدم مفاتيح خارجية، أليس كذلك؟

إذا لم تتمكن من استخدام TRUNCATE TABLE بسبب المفاتيح الخارجية و/أو المشغلات، فيمكنك مراعاة ما يلي:

  • إسقاط كافة الفهارس.
  • قم بالحذف المعتاد؛
  • إعادة إنشاء كافة الفهارس.

قد يؤدي هذا إلى تسريع عملية الحذف إلى حد ما.

سأقوم بمراجعة كلامي السابق:

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

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

من MSDN:

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

أردت فقط أن أقول إن هناك فرقًا جوهريًا بين الاثنين، ونظرًا لوجود فرق، ستكون هناك تطبيقات قد يكون أحدهما أو الآخر غير مناسب.

DELETE * FROM table_name;

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

SELECT DbVendor_SuperFastDeleteAllFunction(tablename, BOZO_BIT) FROM dummy;

بالنسبة للسرعة أعتقد أن الأمر يعتمد على ...

  • قاعدة البيانات الأساسية:أوراكل، مايكروسوفت، MySQL، PostgreSQL، وغيرها، مخصص...

  • الجدول ومحتوياته والجداول المرتبطة به:

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

DROP TABLE table_name;

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

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