मैं विशेष रूप से धीमे डिलीट ऑपरेशन से संबंधित हमारे सिस्टम में से एक में आवर्ती "बग रिपोर्ट" (परफ इश्यू) का विश्लेषण कर रहा हूं। लंबी कहानी छोटी: ऐसा लगता है कि CASCADE DELETE
कुंजी काफी हद तक जिम्मेदार थे, और मैं जानना चाहता हूं (ए) अगर यह समझ में आता है, और (बी) यह मामला क्यों है।क्या SQL सर्वर डीआरआई (हटाए गए कैस्केड पर) धीमा है?
हमारे पास एक स्कीमा है, मान लें, विजेट्स, जो संबंधित तालिकाओं और संबंधित से संबंधित तालिकाओं के बड़े ग्राफ की जड़ पर हैं। पूरी तरह स्पष्ट होने के लिए, इस तालिका से हटाना सक्रिय रूप से निराश है; यह "परमाणु विकल्प" है और इसके विपरीत उपयोगकर्ताओं को कोई भ्रम नहीं है। फिर भी, कभी-कभी इसे कभी करना होगा।
Widgets
|
+--- Anvils [1:1]
| |
| +--- AnvilTestData [1:N]
|
+--- WidgetHistory (1:N)
|
+--- WidgetHistoryDetails (1:N)
स्तंभ परिभाषाएं ऐसा दिखाई देगा:
Widgets (WidgetID int PK, WidgetName varchar(50))
Anvils (AnvilID int PK, WidgetID int FK/IX/UNIQUE, ...)
AnvilTestData (AnvilID int FK/IX, TestID int, ...Test Data...)
WidgetHistory (HistoryID int PK, WidgetID int FK/IX, HistoryDate datetime, ...)
WidgetHistoryDetails (HistoryID int FK/IX, DetailType smallint, ...)
कुछ नहीं भी डरावना, वास्तव में
स्कीमा कुछ इस तरह लग रहा है। Widget
विभिन्न प्रकार हो सकते हैं, Anvil
एक विशेष प्रकार है, ताकि संबंध 1: 1 (या अधिक सटीक 1: 0..1) हो। फिर वहां बड़ी मात्रा में डेटा है - शायद AnvilTestData
प्रति Anvil
की हजारों पंक्तियां, समय के साथ एकत्रित, कठोरता, संक्षारण, सटीक वजन, हथौड़ा संगतता, उपयोगिता संबंधी मुद्दों और कार्टून सिर के साथ प्रभाव परीक्षण से निपटने के लिए।
फिर प्रत्येक Widget
में विभिन्न प्रकार के लेनदेन का एक लंबा, उबाऊ इतिहास है - उत्पादन, सूची चाल, बिक्री, दोष जांच, आरएमए, मरम्मत, ग्राहक शिकायतें आदि। एक विजेट के लिए 10-20k विवरण हो सकते हैं, या उसकी उम्र के आधार पर कोई भी नहीं।
तो, आश्चर्यजनक रूप से, यहां प्रत्येक स्तर पर CASCADE DELETE
संबंध है। यदि Widget
को हटाने की आवश्यकता है, तो इसका मतलब है कि कुछ गलत हो गया है और हमें उस विजेट के किसी भी रिकॉर्ड को मिटाना होगा, जिसमें इतिहास, परीक्षण डेटा इत्यादि शामिल हैं। फिर, परमाणु विकल्प।
संबंध सभी अनुक्रमित हैं, आंकड़े अद्यतित हैं। सामान्य प्रश्न तेजी से होते हैं। प्रणाली हटाए गए सब कुछ के लिए बहुत आसानी से hum के साथ hums। हटाने के लिए देख
DELETE FROM Widgets
WHERE WidgetID = @WidgetID
सुंदर सरल, अहानिकर ...:
यहाँ बात करने के लिए हो रही है, अंत में, विभिन्न कारणों के लिए हम केवल एक बार में एक विजेट को हटाने तो एक हटाने बयान इस प्रकार दिखाई देगा अनुमति देते हैं, के साथ विजेट के लिए चलाने के लिए 2 मिनट से अधिक समय लगता है!
निष्पादन योजनाओं के माध्यम से slogging के बाद मैं अंततः उच्चतम लागत के साथ उप-संचालन के रूप में AnvilTestData
और WidgetHistoryDetails
हटा देता है।
DECLARE @AnvilID int
SELECT @AnvilID = AnvilID FROM Anvils WHERE WidgetID = @WidgetID
DELETE FROM AnvilTestData
WHERE AnvilID = @AnvilID
DELETE FROM WidgetHistory
WHERE HistoryID IN (
SELECT HistoryID
FROM WidgetHistory
WHERE WidgetID = @WidgetID)
DELETE FROM Widgets WHERE WidgetID = @WidgetID
इन "अनुकूलन" के दोनों महत्वपूर्ण speedups के परिणामस्वरूप: तो मैं जैसे निम्नलिखित CASCADE
बंद करने से (लेकिन वास्तविक FK रखने, बस NO ACTION
करने के लिए इसे स्थापित करने) और कुछ के रूप में स्क्रिप्ट को फिर से लिखने में बहुत ज्यादा के साथ प्रयोग , प्रत्येक निष्पादन समय से लगभग एक पूर्ण मिनट शेविंग करता है, ताकि मूल 2-मिनट के विलोपन में लगभग 5-10 सेकंड लगते हैं - कम से कम नए विजेट्स, बिना इतिहास या परीक्षण डेटा के।
बस बिल्कुल स्पष्ट होना करने के लिए, वहां अभी भी है WidgetHistory
से WidgetHistoryDetails
, जहां फैनआउट सबसे अधिक है करने के लिए एक CASCADE
, मैं केवल एक Widgets
से होने वाले हटा दिया।
इसके अलावा झरना संबंधों के "सपाट" में हुई उत्तरोत्तर कम नाटकीय लेकिन अभी भी ध्यान देने योग्य speedups, बात करने के लिए जहां को हटाने के लिए एक नई विजेट एक बार लगभग तात्कालिक था झरना के सभी बड़े टेबल हटा दिया और स्पष्ट के साथ प्रतिस्थापित किया गया करने के लिए हटा देता है हटा देता है।
मैं प्रत्येक परीक्षण से पहले DBCC DROPCLEANBUFFERS
और DBCC FREEPROCCACHE
का उपयोग कर रहा हूं। मैंने उन सभी ट्रिगर्स को अक्षम कर दिया है जो आगे की मंदी पैदा कर सकते हैं (हालांकि वे निष्पादन योजना में वैसे भी दिखाई देंगे)। और मैं पुराने विगेट्स के खिलाफ भी परीक्षण कर रहा हूं, और साथ ही साथ एक महत्वपूर्ण गति को भी देख रहा हूं; हटाए गए जो 5 मिनट लेते थे अब 20-40 सेकंड लेते हैं।
अब मैं "चयन टूटा नहीं गया" दर्शन का उत्साही समर्थक हूं, लेकिन CASCADE DELETE
संबंधों की क्रशिंग, दिमाग-दबाने वाली अक्षमता के अलावा इस व्यवहार के लिए कोई तार्किक स्पष्टीकरण नहीं लगता है।
तो, मेरे सवाल कर रहे हैं:
इस एसक्यूएल सर्वर में डीआरआई के साथ एक ज्ञात समस्या है? (मैं गूगल पर बात की इस तरह का कोई भी संदर्भ के लिए यहां अतः में लग सकता है या नहीं, मुझे लगता है जवाब नहीं है।)
यदि नहीं, तो वहाँ व्यवहार मैं के लिए एक और स्पष्टीकरण है देख के?
यदि यह एक ज्ञात मुद्दा है, तो यह एक मुद्दा क्यों है, और क्या बेहतर कामकाज मैं उपयोग कर सकता हूं? , रिकॉर्ड पर आधारित
स्कीमा? यू निश्चित रूप से एफके के एन पक्ष पर एक साधारण लापता सूचकांक नहीं है? –
@ रीमस: उदाहरण स्कीमा है (यदि कोई विवरण गुम है, तो मुझे बताएं कि आप क्या देखना चाहते हैं)। निश्चित रूप से, 100% सकारात्मक यह एक लापता सूचकांक नहीं है (भले ही यह था, फिर भी दूसरा संस्करण धीमा हो जाएगा, है ना?) – Aaronaught
कुछ कॉलम/इंडेक्स/एफके परिभाषाओं में जोड़ा गया है, जो कि मदद करता है। – Aaronaught