it-swarm.asia

SQL Server "جدول فارغ" بطيء بعد حذف كافة السجلات (12 مليون)؟

لدي مثيل SQL Server 2008 مع 150 عمودًا تقريبًا. لقد قمت مسبقًا بملء هذا الجدول بما يقرب من 12 مليون إدخال ، ولكن منذ ذلك الحين قمت بمسح الجدول استعدادًا لمجموعة بيانات جديدة.

ومع ذلك ، فإن الأوامر التي تم تشغيلها فورًا على جدول فارغ مثل count(*) و select top 1000 في SQL Management Studio تستغرق الآن دهورًا للتشغيل.

SELECT COUNT(*) FROM TABLE_NAME 

استغرق أكثر من 11 دقيقة لإرجاع 0 ، واستغرق SELECT TOP 1000 10 دقائق تقريبًا لإرجاع جدول فارغ.

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

DELETE FROM TABLE_NAME

ماذا يحدث في العالم الذي يجري؟!؟

27
TheDramaLlama

لقد تم إخبارك بالفعل عن سبب TRUNCATE أن يكون أسرع/أفضل/أكثر جنسية من DELETE ، ولكن لا يزال هناك سؤال مطروح لمعالجته:

لماذا SELECT أبطأ بعد اكتمال DELETE؟

وذلك لأن DELETE لديه فقط شبح الصفوف. الجدول كبير مثلما كان عنده 12 مليون صف ، على الرغم من عدم وجود أي صفوف. لحساب الصفوف (0) ، يستغرق الأمر وقتًا طويلاً لحساب عدد 12 مليون صف. في الوقت الذي ستقوم فيه عملية تنظيف الأشباح بتجميع هذه السجلات المظلمة وإلغاء تخصيص الصفحات التي تحتوي على أشباح فقط ، وستسرع SELECTs الخاصة بك. ولكن الآن إذا قمت بالتحقق من Skipped Ghosted Records/sec في perfmon ، فقد يرتفع بشكل كبير خلال SELECT COUNT(*). يمكنك أيضًا تسريع الأمور عن طريق إعادة بناء الجدول: ALTER TABLE ... REBUILD.

TRUNCATE كان سيهتم بهذه المشكلة أيضًا ، لأنها لا تترك أي أشباح وراءها.

انظر أيضًا داخل محرك التخزين: تنظيف الأشباح بعمق .

42
Remus Rusanu

DELETE تحذف العبارات الصفوف من جدول واحد في كل مرة ، وتسجيل كل صف في transaction log ، بالإضافة إلى الاحتفاظ بمعلومات log sequence number (LSN). نظرًا لأنك ذكرت أن جدولك يحتوي على بيانات ضخمة (12 مليون سجل) ، وبعد حذف القرص الصلب الخاص بك من المساحة ، تحقق من حجم ملف سجل قاعدة البيانات. من المحتمل أن يكون قد نما.

كانت الطريقة الأفضل هي:

TRUNCATE TABLE_NAME
13
Akhil

(كان هذا في الأصل تعليقًا على إجابة @ DaveE ، لكني وضعتها في إجابتها الخاصة لأنها طويلة)

TRUNCATE هي عملية مسجلة. يجب أن يكون بخلاف ذلك غير متوافق مع ACID. ومع ذلك ، الاختلافات بين TRUNCATE و DELETE:

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

(* مدى = 8 صفحات. TRUNCATE سيسجل/يزيل النطاقات إذا كانت جميعها من هذا الجدول ، وإلا فسوف يقوم بتسجيل/إزالة الصفحات من النطاقات المختلطة.

** أحد الآثار الجانبية لذلك هو أن DELETE FROM TABLE يمكن أن يترك صفحات فارغة مخصصة للجدول ، اعتمادًا على ما إذا كانت العملية يمكن أن تحصل على قفل حصري للجدول أم لا.)

لذا (العودة إلى السؤال الأصلي) ، TRUNCATE TABLE أفضل بشكل نهائي من DELETE FROM TABLE إذا كنت تفرغ الطاولة ولكنك تريد الاحتفاظ بالهيكل (NB: TRUNCATE can ' t يتم استخدامه على جدول تمت الإشارة إليه بواسطة مفتاح خارجي من جدول آخر).

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

وأخيرًا ، هناك شيء آخر يجب الانتباه إليه - إحصائيات الجدول. شغّل UPDATE STATISTICS <TABLENAME>' after TRUNCATE / DELETE` حتى لا يتعثر مُحسِّن طلب البحث حسب الإحصاءات القديمة.

3
Simon Righarts

(ملاحظة: أنا لست DBA) DELETE هي عملية مسجلة ولا تحرر المساحة المستخدمة. من المحتمل أن يكون لديك سجل معاملات كبير يشغل مساحة ومسحًا للجدول يعمل على مساحة الجدول "الفارغة". أعتقد أنك بحاجة إلى مسح سجل المعاملات وتقليص قاعدة البيانات الخاصة بك. مقالة StackOverflow هذه يجب أن تبدأ.

واستخدم جدول TRUNCATE عندما تريد القيام بذلك في المستقبل.

تحرير: بيان بلدي حول عدم تسجيل TRUNCATE كان خطأ. إزالة.

2
DaveE