سؤال

لدي مجموعة كبيرة جدًا من البيانات (حوالي 3 ملايين سجل) والتي يجب دمجها مع التحديثات والسجلات الجديدة وفقًا لجدول يومي.لدي إجراء مخزن يقوم في الواقع بتقسيم السجل المحدد إلى 1000 قطعة سجل ويستخدم MERGE الأمر باستخدام الجداول المؤقتة في محاولة لتجنب قفل الجدول المباشر أثناء تحديث البيانات.المشكلة هي أنها لا تساعد بالضبط.لا يزال الجدول "مغلقًا" ويتلقى موقعنا الذي يستخدم البيانات مهلات عند محاولة الوصول إلى البيانات.حتى أنني حاولت تقسيمها إلى 100 مقطع تسجيلي وحاولت أيضًا إنشاء ملف WAITFOR DELAY '000:00:5' لمعرفة ما إذا كان من المفيد التوقف مؤقتًا بين دمج القطع.انها لا تزال بطيئة نوعا ما.

أبحث عن أي اقتراحات أو أفضل الممارسات أو أمثلة حول كيفية دمج مجموعات كبيرة من البيانات دون قفل الجداول.

شكرًا

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

المحلول

قم بتغيير الواجهة الأمامية لاستخدام NOLOCK أو READ UNCOMMITTED عند القيام بـ يختار.

لا يمكنك NOLOCK MERGE أو INSERT أو UPDATE حيث يجب قفل السجلات لإجراء التحديث.ومع ذلك، يمكنك عدم قفل التحديدات.

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

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

سيكون المبلغ المثالي هو أن يكون لديك ذاكرة وصول عشوائي كافية لسحب قاعدة البيانات بأكملها إلى الذاكرة حسب الحاجة.على سبيل المثال، إذا كان لديك قاعدة بيانات بسعة 4 جيجابايت، فتأكد من أن لديك ذاكرة وصول عشوائي (RAM) بسعة 8 جيجابايت.في خادم x64 بالطبع.

نصائح أخرى

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

عندما قمنا بدمج سجلات الجدول المصدر عبر نافذة التشغيل بأكملها ثم قمنا بإجراء الدمج مرة واحدة فقط، شهدنا زيادة في الأداء بنسبة 500%.تفسيري لذلك هو أنك تدفع مقابل التحليل المسبق لأمر MERGE مرة واحدة فقط بدلاً من دفعه مرارًا وتكرارًا في حلقة ضيقة.

علاوة على ذلك، أنا متأكد من أن دمج 1.6 مليون صف (المصدر) في 7 ملايين صف (الهدف)، بدلاً من 400 صف في 7 ملايين صف عبر 4000 عملية متميزة (في حالتنا) يزيد من قدرات محرك خادم SQL بشكل أفضل.مرة أخرى، يتم إجراء قدر لا بأس به من العمل في تحليل مجموعتي البيانات ويتم ذلك مرة واحدة فقط.

سؤال آخر يجب أن أطرحه هو ما إذا كنت على علم بأن أمر MERGE يعمل بشكل أفضل مع الفهارس الموجودة في الجدولين المصدر والهدف؟وأود أن أحيلك إلى الرابط التالي:

http://msdn.microsoft.com/en-us/library/cc879317(v=SQL.100).aspx

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

على سبيل المثال:كان لدينا جدول استغرق INSERT فيه 0.2 ثانية مجنونة لكل إدخال، ويبدو أن معظم هذا الوقت تم إهداره في إغلاق المعاملة، لذلك قمنا بتحويل هذا إلى استخدام MERGE وأظهرت بعض الاختبارات السريعة أنه سمح لنا بإدراج 256 إدخالاً في 0.4 ثانية أو حتى 512 في 0.5 ثانية، اختبرنا ذلك باستخدام مولدات التحميل وبدا أن كل شيء على ما يرام، حتى وصل إلى الإنتاج وتم حظر كل شيء على أقفال الصفحة، مما أدى إلى إنتاجية إجمالية أقل بكثير من الإدخالات الفردية.

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

يعد الحصول على تلميحات NOLOCK على جميع قراءات الواجهة الأمامية أمرًا ضروريًا دائمًا.

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