SQL المكررة حذف الاستعلام على الملايين من الصفوف الأداء

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

سؤال

وقد كان مغامرة.لقد بدأت مع حلقات مكررة الاستعلام الموجود في سؤالي السابق, لكن كل حلقة سوف يذهب أكثر من كل 17 مليون سجل, وهذا يعني أنه سيستغرق أسابيع (مجرد تشغيل *select count * from MyTable* يأخذ الخادم 4:30 دقيقة باستخدام MSSQL 2005).انا امع المعلومات من هذا الموقع و في هذا بعد.

و قد وصلت في الاستعلام أدناه.السؤال هو هل هذا هو النوع الصحيح من تشغيل الاستعلام على 17 مليون السجلات في أي نوع من الأداء ؟ إذا لم يكن كذلك ، فما هو ؟

استعلام SQL:

DELETE tl_acxiomimport.dbo.tblacxiomlistings
WHERE RecordID in 
(SELECT RecordID
    FROM tl_acxiomimport.dbo.tblacxiomlistings
    EXCEPT
    SELECT RecordID
    FROM (
        SELECT RecordID, Rank() over (Partition BY BusinessName, latitude, longitude,           Phone ORDER BY webaddress DESC, caption1 DESC, caption2 DESC ) AS Rank
    FROM tl_acxiomimport.dbo.tblacxiomlistings
    ) al WHERE Rank = 1)
هل كانت مفيدة؟

المحلول

رؤية QueryPlan من شأنه أن يساعد.

هل هذا ممكن ؟

SELECT m.*
into #temp
FROM tl_acxiomimport.dbo.tblacxiomlistings m 
inner join (SELECT RecordID, 
                   Rank() over (Partition BY BusinessName, 
                                             latitude,  
                                             longitude,            
                                             Phone  
                                ORDER BY webaddress DESC,  
                                         caption1 DESC,  
                                         caption2 DESC ) AS Rank
              FROM tl_acxiomimport.dbo.tblacxiomlistings
           ) al on (al.RecordID = m.RecordID and al.Rank = 1)

truncate table tl_acxiomimport.dbo.tblacxiomlistings

insert into tl_acxiomimport.dbo.tblacxiomlistings
     select * from #temp

نصائح أخرى

شيء ما حدث مع DB server أو تخزين أو بعض مزيج منها.4:30 select count * يبدو عالية جدا.

تشغيل DBCC_SHOWCONTIG أن ترى كيفية تجزئة الجدول الخاص بك, يمكن أن يسبب هذا الأداء الرئيسية ضرب على الطاولة بهذا الحجم.

أيضا, إضافة إلى تعليق RyanKeeter تشغيل عرض خطة وإذا كان هناك أي عمليات التفحص الجدول إنشاء فهرس PK حقل في هذا الجدول.

لن يكون أكثر بساطة القيام به:

DELETE tl_acxiomimport.dbo.tblacxiomlistings
WHERE RecordID in 
(SELECT RecordID
   FROM (
        SELECT RecordID,
            Rank() over (Partition BY BusinessName,
                                  latitude,
                                  longitude,
                                  Phone
                         ORDER BY webaddress DESC,
                                  caption1 DESC,
                                  caption2 DESC) AS Rank
        FROM tl_acxiomimport.dbo.tblacxiomlistings
        )
  WHERE Rank > 1
  )

تشغيل هذا في "محلل استعلام":

SET SHOWPLAN_TEXT ON

ثم يطلب محلل استعلام تشغيل الاستعلام الخاص بك.بدلا من تشغيل الاستعلام SQL Server سيتم إنشاء خطة الاستعلام ووضعها في مجموعة النتائج.

تبين لنا خطة الاستعلام.

17 مليون سجل هو لا شيء.إذا كان الأمر يستغرق 4:30 إلى مجرد القيام select count(*) ثم هناك مشكلة خطيرة ربما تتعلق إما نقص الذاكرة في الخادم أو حقا المعالج القديم.

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

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

حتى أنك حذف كافة السجلات التي ليست في المرتبة الأولى ؟ قد يكون من المفيد مقارنة الانضمام ضد أعلى 1 الفرعية الاستعلام ضد (والتي قد تعمل أيضا في عام 2000 ، إذ رتبة 2005 وما فوق فقط)

هل تحتاج إلى إزالة جميع التكرارات في عملية واحدة?أفترض أنك preforming نوع من الغرف المهمة ، قد تكون قادرة على القيام بذلك قطعة من الحكمة.

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

اقتراح فوق إلى حدد في جدول مؤقت الأول هو أفضل رهان.هل يمكن أيضا استخدام شيء من هذا القبيل:

set rowcount 1000

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

إذا فهمت بشكل صحيح يمكنك الاستعلام هو نفس

DELETE tl_acxiomimport.dbo.tblacxiomlistings
FROM
    tl_acxiomimport.dbo.tblacxiomlistings allRecords
    LEFT JOIN (   
        SELECT RecordID, Rank() over (Partition BY BusinessName, latitude, longitude, Phone ORDER BY webaddress DESC, caption1 DESC, caption2 DESC ) AS Rank
        FROM tl_acxiomimport.dbo.tblacxiomlistings
        WHERE Rank = 1) myExceptions
    ON allRecords.RecordID = myExceptions.RecordID
WHERE
    myExceptions.RecordID IS NULL

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

في الواقع يمكنك اختبار سرعة النتائج بأمان ببساطة الاتصال SELECT * أو SELECT COUNT(*) على من جزء مثل على سبيل المثال

SELECT *
FROM
    tl_acxiomimport.dbo.tblacxiomlistings allRecords
    LEFT JOIN (   
        SELECT RecordID, Rank() over (Partition BY BusinessName, latitude, longitude, Phone ORDER BY webaddress DESC, caption1 DESC, caption2 DESC ) AS Rank
        FROM tl_acxiomimport.dbo.tblacxiomlistings
        WHERE Rank = 1) myExceptions
    ON allRecords.RecordID = myExceptions.RecordID
WHERE
    myExceptions.RecordID IS NULL

وهذا هو سبب آخر لماذا يفضلون الانضمام إلى النهج آمل أن يساعد

هذا يبدو جيد ولكن كنت قد تنظر في اختيار البيانات في الجدول المؤقت واستخدام ذلك في حذف البيان.لقد لاحظت ضخمة المكاسب الأداء من يفعل هذا بدلا من أن يفعل كل شيء في استعلام واحد.

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

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

SET ROWCOUNT 5000
WHILE 1 = 1
BEGIN
    begin tran
            DELETE FROM ??? WHERE ???
            IF @@rowcount = 0
            BEGIN
               COMMIT
               BREAK
            END
    COMMIT
END
SET ROWCOUNT 0
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top