डेटाबेस डिज़ाइन में उपयोग किया जाने वाला एक सामान्य तत्व बाधा है। बाधाएं विभिन्न प्रकार के स्वादों (जैसे डिफ़ॉल्ट, अद्वितीय) में आती हैं और उस कॉलम की अखंडता को लागू करती हैं जिस पर वे मौजूद हैं। जब अच्छी तरह से लागू किया जाता है, तो डेटाबेस के डिज़ाइन में बाधाएँ एक शक्तिशाली घटक होते हैं क्योंकि वे डेटा को डेटाबेस में आने से रोकते हैं जो निर्धारित मानदंडों को पूरा नहीं करते हैं। हालांकि, WITH NOCHECK
. जैसे कमांड का उपयोग करके बाधाओं का उल्लंघन किया जा सकता है और IGNORE_CONSTRAINTS
. इसके अलावा, REPAIR_ALLOW_DATA_LOSS
. का उपयोग करते समय किसी भी DBCC CHECK
. के साथ विकल्प डेटाबेस भ्रष्टाचार को सुधारने के लिए आदेश, बाधाओं पर विचार नहीं किया जाता है।
नतीजतन, डेटाबेस में अमान्य डेटा होना संभव है - या तो वह डेटा जो किसी बाधा का पालन नहीं करता है, या वह डेटा जो अब अपेक्षित प्राथमिक-विदेशी कुंजी संबंध को बनाए नहीं रखता है। SQL सर्वर में शामिल हैं DBCC CHECKCONSTRAINTS
डेटा खोजने के लिए बयान जो बाधाओं का उल्लंघन करता है। किसी भी मरम्मत विकल्प के निष्पादित होने के बाद, DBCC CHECKCONSTRAINTS
चलाएं पूरे डेटाबेस के लिए यह सुनिश्चित करने के लिए कि कोई समस्या नहीं है, और ऐसे समय हो सकते हैं जब CHECKCONSTRAINTS
चलाना उचित हो चुनिंदा बाधा या तालिका के लिए। डेटा अखंडता बनाए रखना महत्वपूर्ण है, और जबकि DBCC CHECKCONSTRAINTS
चलाना सामान्य नहीं है अमान्य डेटा को खोजने के लिए निर्धारित आधार पर, जब आपको इसे चलाने की आवश्यकता होती है, तो यह समझना एक अच्छा विचार है कि यह क्या प्रदर्शन प्रभाव पैदा कर सकता है।
DBCC CHECKCONSTRAINTS
एकल बाधा, तालिका या संपूर्ण डेटाबेस के लिए निष्पादित कर सकते हैं। अन्य चेक कमांड की तरह, इसे पूरा होने में पर्याप्त समय लग सकता है और सिस्टम संसाधनों का उपभोग करेगा, खासकर बड़े डेटाबेस के लिए। अन्य चेक कमांड के विपरीत, CHECKCONSTRAINTS
डेटाबेस स्नैपशॉट का उपयोग नहीं करता है।
जब हम DBCC CHECKCONSTRAINTS
निष्पादित करते हैं, तो विस्तृत ईवेंट के साथ हम संसाधन उपयोग की जांच कर सकते हैं मेज के लिए। प्रभाव को बेहतर ढंग से दिखाने के लिए, मैंने बड़ी तालिकाएँ बनाने के लिए जोनाथन केहैयस (ब्लॉग | @SQLPoolBoy) से Create Enlarged AdventureWorks Tables.sql स्क्रिप्ट चलाई। जोनाथन की लिपि केवल तालिकाओं के लिए अनुक्रमणिका बनाती है, इसलिए कुछ चयनित बाधाओं को जोड़ने के लिए नीचे दिए गए कथन आवश्यक हैं:
USE [AdventureWorks2012]; GO ALTER TABLE [Sales].[SalesOrderDetailEnlarged] WITH CHECK ADD CONSTRAINT [FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID] FOREIGN KEY([SalesOrderID]) REFERENCES [Sales].[SalesOrderHeaderEnlarged] ([SalesOrderID]) ON DELETE CASCADE; GO ALTER TABLE [Sales].[SalesOrderDetailEnlarged] WITH CHECK ADD CONSTRAINT [CK_SalesOrderDetailEnlarged_OrderQty] CHECK (([OrderQty]>(0))) GO ALTER TABLE [Sales].[SalesOrderDetailEnlarged] WITH CHECK ADD CONSTRAINT [CK_SalesOrderDetailEnlarged_UnitPrice] CHECK (([UnitPrice]>=(0.00))); GO ALTER TABLE [Sales].[SalesOrderHeaderEnlarged] WITH CHECK ADD CONSTRAINT [CK_SalesOrderHeaderEnlarged_DueDate] CHECK (([DueDate]>=[OrderDate])) GO ALTER TABLE [Sales].[SalesOrderHeaderEnlarged] WITH CHECK ADD CONSTRAINT [CK_SalesOrderHeaderEnlarged_Freight] CHECK (([Freight]>=(0.00))) GO
हम sp_helpconstraint
. का उपयोग करके सत्यापित कर सकते हैं कि कौन सी बाधाएं मौजूद हैं :
EXEC sp_helpconstraint '[Sales].[SalesOrderDetailEnlarged]'; GO
sp_helpconstraint आउटपुट
एक बार बाधाएं मौजूद होने पर, हम DBCC CHECKCONSTRAINTS
के लिए संसाधन उपयोग की तुलना कर सकते हैं विस्तारित ईवेंट का उपयोग करके एकल बाधा, तालिका और संपूर्ण डेटाबेस के लिए। सबसे पहले हम एक ऐसा सत्र बनाएंगे जो केवल sp_statement_completed
. को कैप्चर करेगा इवेंट, जिसमें sql_text
. शामिल है कार्रवाई करता है, और आउटपुट को ring_buffer
. पर भेजता है :
CREATE EVENT SESSION [Constraint_Performance] ON SERVER ADD EVENT sqlserver.sp_statement_completed ( ACTION(sqlserver.database_id,sqlserver.sql_text) ) ADD TARGET package0.ring_buffer ( SET max_events_limit=(5000) ) WITH ( MAX_MEMORY=32768 KB, EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY=30 SECONDS, MAX_EVENT_SIZE=0 KB, MEMORY_PARTITION_MODE=NONE, TRACK_CAUSALITY=OFF, STARTUP_STATE=OFF ); GO
इसके बाद हम सत्र शुरू करेंगे और प्रत्येक DBCC CHECKCONSTRAINT
. को चलाएंगे आदेश देता है, फिर रिंग बफर को हेरफेर करने के लिए एक अस्थायी तालिका में आउटपुट करता है। ध्यान दें कि DBCC DROPCLEANBUFFERS
प्रत्येक चेक से पहले निष्पादित करता है ताकि प्रत्येक कोल्ड कैश से शुरू हो, एक स्तरीय परीक्षण क्षेत्र रखते हुए।
ALTER EVENT SESSION [Constraint_Performance] ON SERVER STATE=START; GO USE [AdventureWorks2012]; GO DBCC DROPCLEANBUFFERS; GO DBCC CHECKCONSTRAINTS ('[Sales].[CK_SalesOrderDetailEnlarged_OrderQty]') WITH NO_INFOMSGS; GO DBCC DROPCLEANBUFFERS; GO DBCC CHECKCONSTRAINTS ('[Sales].[FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID]') WITH NO_INFOMSGS; GO DBCC DROPCLEANBUFFERS; GO DBCC CHECKCONSTRAINTS ('[Sales].[SalesOrderDetailEnlarged]') WITH NO_INFOMSGS; GO DBCC DROPCLEANBUFFERS; GO DBCC CHECKCONSTRAINTS WITH ALL_CONSTRAINTS, NO_INFOMSGS; GO DECLARE @target_data XML; SELECT @target_data = CAST(target_data AS XML) FROM sys.dm_xe_sessions AS s INNER JOIN sys.dm_xe_session_targets AS t ON t.event_session_address = s.[address] WHERE s.name = N'Constraint_Performance' AND t.target_name = N'ring_buffer'; SELECT n.value('(@name)[1]', 'varchar(50)') AS event_name, DATEADD(HOUR ,DATEDIFF(HOUR, SYSUTCDATETIME(), SYSDATETIME()),n.value('(@timestamp)[1]', 'datetime2')) AS [timestamp], n.value('(data[@name="duration"]/value)[1]', 'bigint') AS duration, n.value('(data[@name="physical_reads"]/value)[1]', 'bigint') AS physical_reads, n.value('(data[@name="logical_reads"]/value)[1]', 'bigint') AS logical_reads, n.value('(action[@name="sql_text"]/value)[1]', 'varchar(max)') AS sql_text, n.value('(data[@name="statement"]/value)[1]', 'varchar(max)') AS [statement] INTO #EventData FROM @target_data.nodes('RingBufferTarget/event[@name=''sp_statement_completed'']') AS q(n); GO ALTER EVENT SESSION [Constraint_Performance] ON SERVER STATE=STOP; GO
ring_buffer
को पार्स करना एक अस्थायी तालिका में कुछ अतिरिक्त समय लग सकता है (मेरी मशीन पर लगभग 20 सेकंड), लेकिन डेटा की बार-बार पूछताछ एक अस्थायी तालिका से ring_buffer
की तुलना में तेज़ है . यदि हम आउटपुट को देखें तो हम देखते हैं कि प्रत्येक DBCC CHECKCONSTRAINTS
के लिए कई कथन निष्पादित किए गए हैं। :
SELECT * FROM #EventData WHERE [sql_text] LIKE 'DBCC%';
विस्तारित ईवेंट आउटपुट
CHECKCONSTRAINTS
. के आंतरिक कामकाज में खुदाई करने के लिए विस्तारित ईवेंट का उपयोग करना यह एक दिलचस्प कार्य है, लेकिन हम यहां वास्तव में रुचि रखते हैं संसाधन खपत - विशेष रूप से I/O। हम physical_reads
. को एकत्रित कर सकते हैं I/O की तुलना करने के लिए प्रत्येक चेक कमांड के लिए:
SELECT [sql_text], SUM([physical_reads]) AS [Total Reads] FROM #EventData WHERE [sql_text] LIKE 'DBCC%' GROUP BY [sql_text];
चेक के लिए समेकित I/O
एक बाधा की जांच करने के लिए, SQL सर्वर को किसी भी पंक्ति को खोजने के लिए डेटा के माध्यम से पढ़ना पड़ता है जो बाधा का उल्लंघन कर सकता है। CK_SalesOrderDetailEnlarged_OrderQty
. की परिभाषा बाधा है [OrderQty] > 0
. विदेशी कुंजी बाधा, FK_SalesOrderDetailEnlarged_SalesOrderHeaderEnlarged_SalesOrderID
, SalesOrderID
. पर संबंध स्थापित करता है [Sales].[SalesOrderHeaderEnlarged]
. के बीच और [Sales].[SalesOrderDetailEnlarged]
टेबल। सहज रूप से ऐसा लग सकता है कि विदेशी कुंजी बाधा की जाँच के लिए अधिक I/O की आवश्यकता होगी, क्योंकि SQL सर्वर को दो तालिकाओं से डेटा पढ़ना चाहिए। हालांकि, [SalesOrderID]
IX_SalesOrderHeaderEnlarged_SalesPersonID
के लीफ लेवल में मौजूद है [Sales].[SalesOrderHeaderEnlarged]
पर गैर-संकुल अनुक्रमणिका तालिका, और IX_SalesOrderDetailEnlarged_ProductID
. में [Sales].[SalesOrderDetailEnlarged]
. पर अनुक्रमणिका टेबल। जैसे, SQL सर्वर [SalesOrderID]
. की तुलना करने के लिए उन दो इंडेक्स को स्कैन करता है दो तालिकाओं के बीच मान। इसके लिए केवल 19,000 से अधिक पढ़ने की आवश्यकता है। CK_SalesOrderDetailEnlarged_OrderQty
. के मामले में बाधा, [OrderQty]
कॉलम किसी भी इंडेक्स में शामिल नहीं है, इसलिए क्लस्टर इंडेक्स का पूरा स्कैन होता है, जिसके लिए 72,000 से अधिक रीड्स की आवश्यकता होती है।
जब किसी तालिका के लिए सभी बाधाओं की जाँच की जाती है, तो I/O आवश्यकताएँ एकल बाधा की जाँच की तुलना में अधिक होती हैं, और जब पूरे डेटाबेस की जाँच की जाती है, तो वे फिर से बढ़ जाती हैं। ऊपर के उदाहरण में, [Sales].[SalesOrderHeaderEnlarged]
और [Sales].[SalesOrderDetailEnlarged]
तालिकाएँ डेटाबेस में अन्य तालिकाओं की तुलना में अनुपातहीन रूप से बड़ी हैं। वास्तविक दुनिया के परिदृश्यों में यह असामान्य नहीं है; अक्सर डेटाबेस में कई बड़े टेबल होते हैं जिनमें डेटाबेस का एक बड़ा हिस्सा होता है। CHECKCONSTRAINTS
चलाते समय इन तालिकाओं के लिए, जाँच के लिए आवश्यक संभावित संसाधन खपत से अवगत रहें। उपयोगकर्ता के प्रभाव को कम करने के लिए जब भी संभव हो, बंद घंटों के दौरान चेक चलाएं। यदि सामान्य व्यावसायिक घंटों के दौरान चेक चल रहे हों, तो यह समझना कि क्या बाधाएं मौजूद हैं, और सत्यापन का समर्थन करने के लिए कौन से इंडेक्स मौजूद हैं, चेक के प्रभाव को मापने में मदद कर सकते हैं। आप प्रदर्शन प्रभाव को समझने के लिए पहले एक परीक्षण या विकास के माहौल में जांच निष्पादित कर सकते हैं, लेकिन फिर हार्डवेयर, तुलनीय डेटा, आदि के आधार पर भिन्नताएं मौजूद हो सकती हैं। और अंत में, याद रखें कि जब भी आप एक चेक कमांड चलाते हैं जिसमें REPAIR_ALLOW_DATA_LOSS
विकल्प, DBCC CHECKCONSTRAINTS
. के साथ मरम्मत का पालन करें . डेटाबेस की मरम्मत किसी भी बाधा को ध्यान में नहीं रखती है क्योंकि भ्रष्टाचार ठीक हो गया है, इसलिए संभावित रूप से डेटा खोने के अलावा, आप डेटा के साथ समाप्त हो सकते हैं जो आपके डेटाबेस में एक या अधिक बाधाओं का उल्लंघन करता है।