سؤال

استعلام الذي يستخدم في حلقة من خلال 17 ملايين السجلات لإزالة التكرارات وقد تم تشغيل الآن عن 16 ساعة و أردت أن أعرف إذا كان الاستعلام توقفت الآن إذا كان سيتم الانتهاء من حذف البيانات أو إذا كان قد تم حذف أثناء تشغيل هذا الاستعلام?في الواقع, إذا كنت لا تتوقف عن ذلك ، فإنه الانتهاء من حذف أو لفات مرة أخرى ؟

لقد وجدت أنه عندما أقوم

 select count(*) from myTable

أن الصفوف التي تقوم بإرجاع (حين نفعل هذا الاستعلام) حوالي 5 أقل من ما يبدأ الصف العد.من الواضح موارد الخادم سيئة للغاية ، فهل يعني ذلك أن هذه العملية قد استغرقت 16 ساعة من العثور على 5 التكرارات (عندما في الواقع هناك الآلاف) ، وهذا يمكن أن تكون قيد التشغيل الأيام ؟

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

أي أفكار ؟

أدناه هو الاستعلام:

--Declare the looping variable
DECLARE @LoopVar char(10)


    DECLARE
     --Set private variables that will be used throughout
      @long DECIMAL,
      @lat DECIMAL,
      @phoneNumber char(10),
      @businessname varchar(64),
      @winner char(10)

    SET @LoopVar = (SELECT MIN(RecordID) FROM MyTable)

    WHILE @LoopVar is not null
    BEGIN

      --initialize the private variables (essentially this is a .ctor)
      SELECT 
        @long = null,
        @lat = null,
        @businessname = null,
        @phoneNumber = null,
        @winner = null

      -- load data from the row declared when setting @LoopVar  
      SELECT
        @long = longitude,
        @lat = latitude,
        @businessname = BusinessName,
        @phoneNumber = Phone
      FROM MyTable
      WHERE RecordID = @LoopVar

      --find the winning row with that data. The winning row means 
      SELECT top 1 @Winner = RecordID
      FROM MyTable
      WHERE @long = longitude
        AND @lat = latitude
        AND @businessname = BusinessName
        AND @phoneNumber = Phone
      ORDER BY
        CASE WHEN webAddress is not null THEN 1 ELSE 2 END,
        CASE WHEN caption1 is not null THEN 1 ELSE 2 END,
        CASE WHEN caption2 is not null THEN 1 ELSE 2 END,
        RecordID

      --delete any losers.
      DELETE FROM MyTable
      WHERE @long = longitude
        AND @lat = latitude
        AND @businessname = BusinessName
        AND @phoneNumber = Phone
        AND @winner != RecordID

      -- prep the next loop value to go ahead and perform the next duplicate query.
      SET @LoopVar = (SELECT MIN(RecordID) 
    FROM MyTable
    WHERE @LoopVar < RecordID)
    END
هل كانت مفيدة؟

المحلول

لا sql server استرجاع محذوفات أنه قد قام بالفعل إذا قمت بإيقاف تنفيذ الاستعلام.أوراكل يتطلب صريحة لارتكاب عمل استفسارات أو بيانات يحصل على التراجع ، ولكن ليس mssql.

مع sql server انها لن تتراجع إلا إذا كنت على وجه التحديد تعمل في إطار الصفقة و يمكنك التراجع عن تلك الصفقة ، أو اتصال يغلق دون المعاملات في ارتكابها.ولكن أنا لا أرى معاملة السياق في الاستعلام أعلاه.

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

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

نصائح أخرى

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

أنا على وجه التحديد اختبار هذا نفسي على نفسي SQL Server باستخدام الاستعلام التالي ، ApplicationLog طاولة فارغة على الرغم من أنني إلغاء الاستعلام:

declare @count int
select @count = 5
WHILE @count > 0
BEGIN
  print @count
  delete from applicationlog;
  waitfor time '20:00';
  select @count = @count -1
END

ومع ذلك الاستعلام الخاص بك من المرجح أن يستغرق عدة أيام أو أسابيع أطول من ذلك بكثير ثم 15 ساعة.التقدير الخاص بك التي يمكنك أن عملية 2000 يسجل كل 6 ثوان خطأ لأن كل التكرار في حلقة من الوقت سوف يستغرق وقتا أطول بكثير مع 17 مليون الصفوف ثم يفعل مع 2000 الصفوف.لذلك ما لم الاستعلام الخاص بك يأخذ أقل بشكل ملحوظ ثم الثانية عام 2000 الصفوف ، وسوف يستغرق أيام لجميع 17 مليون دولار.

يجب طرح سؤال جديد حول كيف يمكنك حذف الصفوف المكررة بكفاءة.

إذا كنت لا تفعل أي شيء صريح عن المعاملات ثم سيتم الاتصال في ونتوقع المعاملات الوضعية.في هذه الوضعية كل SQL يعتبر الصفقة.

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

هناك لا يبدو أن يكون أي نقاش من هذا في وصف حين بناء على MSDN.ومع ذلك, منذ فترة البيان لا يمكن مباشرة تعديل قاعدة البيانات فإنه يبدو من المنطقي أن لا بدء تشغيل السيارات-ارتكاب الصفقة.

ضمني المعاملات

إذا لا الضمني المعاملات ، ثم كل التكرار في حلقة ارتكب التغييرات.

فمن الممكن على أي ملقم SQL أن يكون مع مجموعة 'ضمني المعاملات.هذا هو إعداد قاعدة بيانات (الافتراضي هو إيقاف).هل يمكن أن يكون أيضا الضمني المعاملات في خصائص معينة الاستعلام داخل إدارة Studio (انقر بزر الماوس الأيمن في جزء الاستعلام>خيارات) ، من خلال الإعدادات الافتراضية في العميل ، أو مجموعة البيان.

SET IMPLICIT_TRANSACTIONS ON;

في كلتا الحالتين, إذا كان هذا هو الحال, كنت لا تزال بحاجة إلى تنفيذ صريحة لارتكاب/الاستعادة بغض النظر وقف تنفيذ الاستعلام.


ضمني المعاملات المرجعية:

http://msdn.microsoft.com/en-us/library/ms188317.aspx

http://msdn.microsoft.com/en-us/library/ms190230.aspx

لقد ورثت النظام الذي كان المنطق شيء من هذا القبيل لك تنفيذها في SQL.في حالتنا كنا نحاول ربط الصفوف باستخدام مطابقة غامض أن أسماء مشابهة/عناوين الخ و هذا المنطق تم بحتة في SQL.في الوقت الذي ورثته كان لدينا حوالي 300 ، 000 الصفوف في الجدول حسب التوقيت ، حسبنا سوف يستغرق سنة لتتناسب مع كل منهم.

كتجربة لمعرفة كيف أسرع بكثير أنني يمكن أن تفعل ذلك خارج SQL كتبت برنامج تفريغ الجدول ديسيبل في ملفات مسطحة, قراءة مسطحة الملفات في C++ برنامج بناء بلدي الفهارس و لا المنطق الضبابي هناك ، ثم إعادة استيراد ملفات مسطحة في قاعدة البيانات.ما استغرق سنة في SQL استغرق حوالي 30 ثانية في C++ التطبيق.

لذلك, نصيحتي, لا تحاول حتى ما تقومون به في SQL.تصدير, عملية, إعادة الاستيراد.

يحذف التي تم تنفيذها حتى هذه اللحظة لن يتم التراجع.


لأن المؤلف الأصلي الرمز في السؤال, و بعد أن أصدرت التحذير من أن الأداء يعتمد على الفهارس ، أقترح البنود التالية لتسريع هذا.

RecordId من الأفضل أن يكون المفتاح الأساسي.أنا لا أقصد الهوية ، أعني المفتاح الأساسي.تؤكد ذلك باستخدام sp_help

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

SELECT *
FROM MyTable
WHERE @long = longitude
  AND @lat = latitude
  AND @businessname = BusinessName
  AND @phoneNumber = Phone

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

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

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

أعتقد أن هذا الاستعلام سيكون أكثر فاعلية إذا تم إعادة كتابة باستخدام واحد يمر الخوارزمية باستخدام المؤشر.كنت آمرك المؤشر الجدول حسب خط الطول وخط العرض BusinessName و @phoneNumber.كنت خطوة من خلال الصفوف في وقت واحد.إذا صف واحد له نفس خط الطول وخط العرض businessname ، phonenumber كما الصف السابق ، ثم حذفه.

أعتقد أن عليك أن تنظر بجدية في الخاص بك methodolology.عليك أن تبدأ التفكير في مجموعات (على الرغم من أن الأداء قد تحتاج تجهيز الدفعات ، ولكن ليس من صف مقابل 17 مليون سجل الجدول.)

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

شيء مثل (ملاحظة أنا لم أكتب إنشاء فهرس البيانات, أعتقد يمكنك أن تبحث في نفسك):

SELECT min(m.RecordID), m.longitude, m.latitude, m.businessname, m.phone  
     into  #RecordsToKeep    
FROM MyTable   m
join 
(select longitude, latitude, businessname, phone
from MyTable
group by longitude, latitude, businessname, phone
having count(*) >1) a 
on a.longitude = m.longitude and a.latitude = m.latitude and
a.businessname = b.businessname and a.phone = b.phone 
group by  m.longitude, m.latitude, m.businessname, m.phone   
ORDER BY CASE WHEN m.webAddress is not null THEN 1 ELSE 2 END,        
    CASE WHEN m.caption1 is not null THEN 1 ELSE 2 END,        
    CASE WHEN m.caption2 is not null THEN 1 ELSE 2 END



while (select count(*) from #RecordsToKeep) > 0
begin
select top 1000 * 
into #Batch
from #RecordsToKeep

Delete m
from mytable m
join #Batch b 
        on b.longitude = m.longitude and b.latitude = m.latitude and
        b.businessname = b.businessname and b.phone = b.phone 
where r.recordid <> b.recordID

Delete r
from  #RecordsToKeep r
join #Batch b on r.recordid = b.recordid

end

Delete m
from mytable m
join #RecordsToKeep r 
        on r.longitude = m.longitude and r.latitude = m.latitude and
        r.businessname = b.businessname and r.phone = b.phone 
where r.recordid <> m.recordID

أيضا محاولة التفكير في طريقة أخرى لإزالة الصفوف المكررة:

delete t1 from table1 as t1 where exists (
    select * from table1 as t2 where
        t1.column1=t2.column1 and
        t1.column2=t2.column2 and
        t1.column3=t2.column3 and
        --add other colums if any
        t1.id>t2.id
)

أفترض أن لديك عدد صحيح معرف العمود في الجدول الخاص بك.

إذا كان الجهاز الخاص بك ليس لديها أجهزة متقدمة ثم قد يستغرق sql server وقتا طويلا جدا لإكمال هذا الأمر.لا نعرف بالتأكيد كيف يتم تنفيذ هذه العملية تحت غطاء محرك السيارة ولكن بناء على تجربتي ويمكن أن يتم ذلك بشكل أكثر كفاءة من خلال جلب السجلات من قاعدة البيانات في الذاكرة على البرنامج الذي يستخدم هيكل الشجرة مع إزالة مكررة حكم الإدراج.محاولة قراءة مجمل الجدول في chuncks (أقول 10000 الصفوف في وقت واحد) في C++ برنامج باستخدام ODBC.مرة واحدة في C++ برنامج استخدام std::خريطة أين المفتاح هو مفتاح فريد و البنية هي البنية التي يحمل بقية البيانات في المتغيرات.حلقة على جميع السجلات وإجراء الإدراج في الخريطة.الخريطة إدراج دالة سيتم التعامل مع إزالة التكرارات.لأن البحث داخل الخريطة lg(ن) وقت أقل بكثير من الوقت للعثور على التكرارات من استخدام الخاص بك أثناء الحلقة.يمكنك ثم حذف الجدول بأكمله إضافة الصفوف مرة أخرى إلى قاعدة البيانات من على الخريطة من خلال تشكيل إدراج الاستفسارات وتنفيذها عبر odbc أو بناء النص الملف النصي يعمل في إدارة studio.

أنا متأكد أن النتيجة سلبية.وإلا ما الفائدة من المعاملات ؟

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