परिचय
न्यूनतम लॉगिंग प्राप्त करना INSERT...SELECT
. का उपयोग करके एक खाली . में संकुल अनुक्रमणिका लक्ष्य उतना आसान नहीं है जितना डेटा प्रदर्शन लोडिंग मार्गदर्शिका . में वर्णित है ।
यह पोस्ट नए विवरण provides प्रदान करती है न्यूनतम लॉगिंग . के लिए आवश्यकताओं के बारे में जब सम्मिलित लक्ष्य एक खाली पारंपरिक संकुल सूचकांक है। (वहां "पारंपरिक" शब्द में कॉलमस्टोर . शामिल नहीं है और स्मृति-अनुकूलित ('हेकाटन') संकुल सारणी)। लक्ष्य तालिका के ढेर होने पर लागू होने वाली शर्तों के लिए, इस श्रृंखला का पिछला लेख देखें।
संकलित तालिकाओं का सारांश
डेटा लोडिंग प्रदर्शन मार्गदर्शिका न्यूनतम लॉगिंग . के लिए आवश्यक शर्तों का एक उच्च-स्तरीय सारांश शामिल है संकुल तालिकाओं में:
यह पोस्ट केवल शीर्ष पंक्ति . से संबंधित है . इसमें कहा गया है कि TABLOCK
और ORDER
संकेत आवश्यक हैं, एक नोट के साथ जो कहता है:
यदि बल्क इंसर्ट का उपयोग कर रहे हैं तो ऑर्डर हिंट का उपयोग किया जाना चाहिए।
टेबल लॉक के साथ खाली लक्ष्य
सारांश शीर्ष पंक्ति से पता चलता है कि सभी एक खाली संकुल अनुक्रमणिका में प्रविष्टियां न्यूनतम रूप से लॉग की जाएंगी जब तक TABLOCK
और ORDER
संकेत निर्दिष्ट हैं। TABLOCK
RowSetBulk
. को सक्षम करने के लिए संकेत आवश्यक है हीप टेबल बल्क लोड के लिए उपयोग की जाने वाली सुविधा। एक ORDER
यह सुनिश्चित करने के लिए संकेत आवश्यक है कि पंक्तियाँ क्लस्टर इंडेक्स इंसर्ट पर पहुंचें लक्ष्य अनुक्रमणिका में योजना संचालक कुंजी क्रम . इस गारंटी के बिना, SQL सर्वर उन अनुक्रमणिका पंक्तियों को जोड़ सकता है जो सही ढंग से क्रमबद्ध नहीं हैं, जो अच्छा नहीं होगा।
अन्य बल्क लोडिंग विधियों के विपरीत, यह संभव नहीं . है आवश्यक ORDER
निर्दिष्ट करने के लिए INSERT...SELECT
. पर संकेत दें बयान। यह संकेत समान नहीं है ORDER BY
. का उपयोग करने के रूप में INSERT...SELECT
. पर क्लॉज बयान। एक ORDER BY
INSERT
. पर क्लॉज केवल किसी भी पहचान . के तरीके की गारंटी देता है मान असाइन किए गए हैं, पंक्ति डालने का क्रम नहीं।
INSERT...SELECT
. के लिए , SQL सर्वर अपना स्वयं का निर्धारण करता है क्या यह सुनिश्चित करना है कि पंक्तियों को क्लस्टर इंडेक्स इंसर्ट में प्रस्तुत किया गया है कुंजी क्रम में ऑपरेटर या नहीं। इस आकलन का परिणाम DMLRequestSort
. के माध्यम से निष्पादन योजनाओं में दिखाई देता है सम्मिलित करें . की संपत्ति ऑपरेटर। DMLRequestSort
संपत्ति होनी चाहिए सत्य . पर सेट करें INSERT...SELECT
. के लिए एक इंडेक्स में न्यूनतम लॉग इन . होने के लिए . जब इसे गलत . पर सेट किया जाता है , न्यूनतम लॉगिंग नहीं हो सकता।
DMLRequestSort
होने के कारण सत्य पर सेट करें केवल स्वीकार्य गारंटी . है SQL सर्वर के लिए इनपुट ऑर्डरिंग सम्मिलित करें। कोई व्यक्ति निष्पादन योजना का निरीक्षण कर सकता है और पूर्वानुमान कि पंक्तियों को क्लस्टर इंडेक्स क्रम में आना चाहिए/होना चाहिए, लेकिन विशिष्ट आंतरिक गारंटी के बिना DMLRequestSort
. द्वारा प्रदान किया गया , यह आकलन कोई मायने नहीं रखता।
जब DMLRequestSort
सच है , SQL सर्वर हो सकता है स्पष्ट क्रमबद्ध करें . का परिचय दें निष्पादन योजना में ऑपरेटर। यदि यह आंतरिक रूप से अन्य तरीकों से आदेश देने की गारंटी दे सकता है, तो क्रमबद्ध करें छोड़ा जा सकता है। यदि सॉर्ट और नो-सॉर्ट दोनों विकल्प उपलब्ध हैं, तो अनुकूलक एक लागत-आधारित . बना देगा पसंद। लागत विश्लेषण न्यूनतम लॉगिंग . के लिए जिम्मेदार नहीं है सीधे; यह अनुक्रमिक I/O के अपेक्षित लाभों और पृष्ठ विभाजन से बचने से प्रेरित है।
DMLRequestSort शर्तें
SQL सर्वर के लिए DMLRequestSort
सेट करने के लिए निम्नलिखित दोनों परीक्षण पास होने चाहिए करने के लिए सच टेबल लॉकिंग के साथ एक खाली क्लस्टर इंडेक्स में डालने पर निर्दिष्ट:
- 250 से अधिक पंक्तियों का अनुमान क्लस्टर इंडेक्स इंसर्ट . के इनपुट साइड पर ऑपरेटर; और
- एक अनुमानित 2 से अधिक पृष्ठों . का डेटा आकार . अनुमानित डेटा आकार एक पूर्णांक नहीं है, इसलिए 2.001 पृष्ठों का परिणाम इस शर्त को पूरा करेगा।
(यह आपको ढेर न्यूनतम लॉगिंग . के लिए शर्तों की याद दिला सकता है , लेकिन आवश्यक अनुमानित यहाँ डेटा का आकार आठ के बजाय दो पेज का है।)
डेटा आकार की गणना
अनुमानित डेटा आकार यहां गणना ढेर के लिए पिछले लेख में वर्णित समान विचित्रताओं के अधीन है, सिवाय इसके कि 8-बाइट RID मौजूद नहीं है।
SQL सर्वर 2012 और उससे पहले के लिए, इसका अर्थ है 5 अतिरिक्त बाइट्स प्रति पंक्ति डेटा आकार गणना में शामिल हैं:एक आंतरिक बिट . के लिए एक बाइट ध्वज, और अद्वितीय . के लिए चार बाइट्स (अद्वितीय अनुक्रमणिका के लिए भी गणना में उपयोग किया जाता है, जो अद्वितीय . को संग्रहीत नहीं करता है )।
SQL सर्वर 2014 और बाद के संस्करण के लिए, अद्वितीय अद्वितीय . के लिए सही ढंग से छोड़ा गया है अनुक्रमणिका, लेकिन एक अतिरिक्त बाइट आंतरिक बिट . के लिए झंडा बरकरार है।
डेमो
निम्न स्क्रिप्ट को नए परीक्षण डेटाबेस में विकास SQL सर्वर इंस्टेंस पर चलाया जाना चाहिए SIMPLE
का उपयोग करने के लिए सेट करें या BULK_LOGGED
पुनर्प्राप्ति मॉडल।
डेमो 268 पंक्तियों को INSERT...SELECT
. का उपयोग करके एक नई क्लस्टर तालिका में लोड करता है TABLOCK
के साथ , और उत्पन्न लेनदेन लॉग रिकॉर्ड पर रिपोर्ट।
IF OBJECT_ID(N'dbo.Test', N'U') IS NOT NULL BEGIN DROP TABLE dbo.Test; END; GO CREATE TABLE dbo.Test ( id integer NOT NULL IDENTITY CONSTRAINT [PK dbo.Test (id)] PRIMARY KEY, c1 integer NOT NULL, padding char(45) NOT NULL DEFAULT '' ); GO -- Clear the log CHECKPOINT; GO -- Insert rows INSERT dbo.Test WITH (TABLOCK) (c1) SELECT TOP (268) CHECKSUM(NEWID()) FROM master.dbo.spt_values AS SV; GO -- Show log entries SELECT FD.Operation, FD.Context, FD.[Log Record Length], FD.[Log Reserve], FD.AllocUnitName, FD.[Transaction Name], FD.[Lock Information], FD.[Description] FROM sys.fn_dblog(NULL, NULL) AS FD; GO -- Count the number of fully-logged rows SELECT [Fully Logged Rows] = COUNT_BIG(*) FROM sys.fn_dblog(NULL, NULL) AS FD WHERE FD.Operation = N'LOP_INSERT_ROWS' AND FD.Context = N'LCX_CLUSTERED' AND FD.AllocUnitName = N'dbo.Test.PK dbo.Test (id)';
(यदि आप SQL Server 2012 या इससे पहले की स्क्रिप्ट चलाते हैं, तो TOP
. बदलें 268 से 252 तक लिपि में खंड, उन कारणों के लिए जिन्हें एक पल में समझाया जाएगा।)
आउटपुट से पता चलता है कि सम्मिलित की गई सभी पंक्तियाँ पूरी तरह से लॉग . थीं खाली . के बावजूद लक्ष्य संकुल तालिका और TABLOCK
संकेत:
परिकलित सम्मिलित डेटा आकार
क्लस्टर इंडेक्स इंसर्ट . के निष्पादन योजना गुण ऑपरेटर दिखाता है कि DMLRequestSort
गलत . पर सेट है . ऐसा इसलिए है क्योंकि सम्मिलित करने के लिए पंक्तियों की अनुमानित संख्या 250 से अधिक है (पहली आवश्यकता को पूरा करते हुए), गणना की गई डेटा आकार नहीं . करता है दो 8KB पृष्ठों से अधिक।
गणना विवरण (एसक्यूएल सर्वर 2014 आगे के लिए) इस प्रकार हैं:
- कुल निश्चित लंबाई स्तंभ का आकार =54 बाइट्स :
- टाइप आईडी 104
bit
=1 बाइट (आंतरिक)। - आईडी 56 टाइप करें
integer
=4 बाइट्स (id
कॉलम)। - आईडी 56 टाइप करें
integer
=4 बाइट्स (c1
कॉलम)। - टाइप आईडी 175
char(45)
=45 बाइट्स (padding
कॉलम)।
- टाइप आईडी 104
- शून्य बिटमैप =3 बाइट्स ।
- पंक्ति शीर्षलेख ओवरहेड =4 बाइट्स ।
- पंक्ति का परिकलित आकार =54 + 3 + 4 =61 बाइट्स ।
- परिकलित डेटा आकार =61 बाइट्स * 268 पंक्तियाँ =16,348 बाइट्स ।
- गणना किए गए डेटा पृष्ठ =16,384 / 8192 =1.99560546875 ।
परिकलित पंक्ति आकार (61 बाइट्स) वास्तविक पंक्ति संग्रहण आकार (60 बाइट्स) से इंसर्ट स्ट्रीम में मौजूद आंतरिक मेटाडेटा के अतिरिक्त एक बाइट से भिन्न होता है। गणना पृष्ठ शीर्षलेख द्वारा प्रत्येक पृष्ठ पर उपयोग किए गए 96 बाइट्स, या पंक्ति संस्करण ओवरहेड जैसी अन्य चीजों के लिए भी जिम्मेदार नहीं है। SQL Server 2012 पर समान गणना uniquifier . के लिए प्रति पंक्ति एक और 4 बाइट जोड़ता है (जो पहले बताए अनुसार अद्वितीय अनुक्रमणिका में मौजूद नहीं है)। अतिरिक्त बाइट्स का मतलब है कि प्रत्येक पृष्ठ पर कम पंक्तियों के फिट होने की उम्मीद है:
- पंक्ति का परिकलित आकार =61 + 4 =65 बाइट्स ।
- परिकलित डेटा आकार =65 बाइट्स * 252 पंक्तियाँ =16,380 बाइट्स
- गणना किए गए डेटा पृष्ठ =16,380 / 8192 =1.99951171875 ।
TOP
बदलना 268 पंक्तियों से 269 (या 2012 के लिए 252 से 253 तक) का खंड अपेक्षित डेटा आकार की गणना करता है बस 2 पेज की न्यूनतम सीमा पर टिप:
- एसक्यूएल सर्वर 2014
- 61 बाइट्स * 269 पंक्तियाँ =16,409 बाइट्स।
- 16,409 / 8192 =2.0030517578125 पेज.
- एसक्यूएल सर्वर 2012
- 65 बाइट्स * 253 पंक्तियाँ =16,445 बाइट्स।
- 16,445 / 8192 =2.0074462890625 पेज.
दूसरी शर्त के साथ अब भी संतुष्ट, DMLRequestSort
सत्य . पर सेट है , और न्यूनतम लॉगिंग हासिल किया गया है, जैसा कि नीचे दिए गए आउटपुट में दिखाया गया है:
रुचि के कुछ अन्य बिंदु:
- पूरी तरह से लॉग किए गए संस्करण के लिए 328 की तुलना में कुल 79 लॉग रिकॉर्ड जेनरेट किए गए हैं। कम लॉग रिकॉर्ड न्यूनतम लॉगिंग का अपेक्षित परिणाम हैं।
LOP_BEGIN_XACT
न्यूनतम लॉग किए गए . में रिकॉर्ड रिकॉर्ड अपेक्षाकृत बड़ी मात्रा में लॉग स्पेस (प्रत्येक में 9436 बाइट्स) आरक्षित करते हैं।- लॉग रिकॉर्ड में सूचीबद्ध लेनदेन नामों में से एक है “ऑफ़लाइन इंडेक्स बिल्ड” . हालांकि हमने किसी इंडेक्स को इस तरह बनाने के लिए नहीं कहा था, एक खाली इंडेक्स में बल्क लोडिंग रो अनिवार्य रूप से एक ही ऑपरेशन है।
- पूरी तरह से लॉग किया हुआ इंसर्ट एक टेबल-लेवल एक्सक्लूसिव लॉक लेता है (
Tab-X
), जबकि न्यूनतम लॉग किया गया सम्मिलित करें स्कीमा संशोधन लेता है (Sch-M
) ठीक वैसे ही जैसे एक 'असली' ऑफ़लाइन इंडेक्स बिल्ड करता है। INSERT...SELECT
. का उपयोग करके एक खाली क्लस्टर तालिका को थोक में लोड किया जा रहा हैTABLOCK
के साथ औरDMRequestSort
सत्य पर सेट करेंRowsetBulk
. का उपयोग करता है तंत्र, ठीक वैसे ही जैसे न्यूनतम लॉग किया हुआ ढेर लोड पिछले लेख में किया था।
कार्डिनैलिटी अनुमान
कम कार्डिनैलिटी अनुमान . से सावधान रहें क्लस्टर इंडेक्स इंसर्ट . पर ऑपरेटर। अगर DMLRequestSort
set को सेट करने के लिए किसी भी थ्रेशोल्ड की आवश्यकता है करने के लिए सच कार्डिनैलिटी के गलत अनुमान के कारण नहीं पहुंचा है, तो इंसर्ट पूरी तरह से लॉग हो जाएगा , निष्पादन समय पर सामने आई पंक्तियों की वास्तविक संख्या और कुल डेटा आकार की परवाह किए बिना।
उदाहरण के लिए, TOP
. को बदलना एक निश्चित कार्डिनैलिटी में एक चर परिणाम का उपयोग करने के लिए डेमो स्क्रिप्ट में क्लॉज अनुमान करें 100 पंक्तियों में से, जो न्यूनतम 251 पंक्ति से कम है:
-- Insert rows DECLARE @NumRows bigint = 269; INSERT dbo.Test WITH (TABLOCK) (c1) SELECT TOP (@NumRows) CHECKSUM(NEWID()) FROM master.dbo.spt_values AS SV;
प्लान कैशिंग
DMLRequestSort
संपत्ति को संचित योजना के भाग के रूप में सहेजा जाता है। जब कैश्ड योजना का पुन:उपयोग किया जाता है , DMLRequestSort
. का मान पुनर्गणना नहीं की गई है निष्पादन समय पर, जब तक कि कोई पुनर्संकलन न हो। ध्यान दें कि TRIVIAL
. के लिए पुनर्संकलन नहीं होता है आँकड़ों या तालिका कार्डिनैलिटी में परिवर्तन के आधार पर योजनाएँ।
कैशिंग के कारण किसी भी अप्रत्याशित व्यवहार से बचने का एक तरीका OPTION (RECOMPILE)
का उपयोग करना है संकेत देना। यह DMLRequestSort
. के लिए उपयुक्त सेटिंग सुनिश्चित करेगा प्रत्येक निष्पादन पर एक संकलन की कीमत पर पुनर्गणना की जाती है।
ट्रेस फ्लैग
DMLRequestSort
को बाध्य करना संभव है सत्य . पर सेट होने के लिए अदस्तावेजीकृत और असमर्थित . सेट करके ट्रेस फ्लैग 2332, जैसा कि मैंने डेटा बदलने वाले टी-एसक्यूएल प्रश्नों को ऑप्टिमाइज़ करने में लिखा था। दुर्भाग्य से, यह नहीं करता है न्यूनतम लॉगिंग . को प्रभावित करें खाली क्लस्टर टेबल के लिए पात्रता - इंसर्ट का अनुमान अभी भी 250 से अधिक पंक्तियों और 2 पृष्ठों पर होना चाहिए। यह ट्रेस फ़्लैग अन्य न्यूनतम-लॉगिंग . को प्रभावित करता है परिदृश्य, जो इस श्रृंखला के अंतिम भाग में शामिल हैं।
सारांश
एक खाली का बल्क लोड हो रहा है INSERT...SELECT
. का उपयोग करके संकुल अनुक्रमणिका RowsetBulk
का पुन:उपयोग करता है हीप टेबल को बल्क लोड करने के लिए इस्तेमाल किया जाने वाला तंत्र। इसके लिए टेबल लॉकिंग की आवश्यकता होती है (आमतौर पर TABLOCK
. के साथ हासिल की जाती है संकेत) और एक ORDER
संकेत देना। ORDER
जोड़ने का कोई तरीका नहीं है INSERT...SELECT
. की ओर संकेत करें बयान। परिणामस्वरूप, न्यूनतम लॉगिंग achieving प्राप्त करना एक खाली संकुल तालिका में यह आवश्यक है कि DMLRequestSort
क्लस्टर इंडेक्स इंसर्ट . की संपत्ति ऑपरेटर सत्य . पर सेट है . यह गारंटी देता है SQL सर्वर के लिए जो पंक्तियाँ सम्मिलित करें . को प्रस्तुत की गई हैं ऑपरेटर लक्ष्य सूचकांक कुंजी क्रम में पहुंचेगा। प्रभाव वैसा ही है जैसा ORDER
. का उपयोग करते समय होता है अन्य बल्क इंसर्ट विधियों जैसे BULK INSERT
. के लिए संकेत उपलब्ध हैं और bcp
।
DMLRequestSort
. के क्रम में सत्य . पर सेट होने के लिए , वहाँ होना चाहिए:
- 250 से अधिक पंक्तियां अनुमानित डाला जाना; और
- एक अनुमानित दो पृष्ठों से अधिक का डेटा आकार सम्मिलित करें ।
अनुमानित डेटा आकार गणना सम्मिलित करें नहीं निष्पादन योजना को गुणा करने के परिणाम से मिलान करें पंक्तियों की अनुमानित संख्या और अनुमानित पंक्ति आकार सम्मिलित करें . के इनपुट पर गुण ऑपरेटर। आंतरिक गणना (गलत तरीके से) में सम्मिलित स्ट्रीम में एक या अधिक आंतरिक कॉलम शामिल हैं, जो अंतिम अनुक्रमणिका में कायम नहीं हैं। आंतरिक गणना भी पेज हेडर या पंक्ति संस्करण जैसे अन्य ओवरहेड्स के लिए जिम्मेदार नहीं है।
परीक्षण या डिबगिंग करते समय न्यूनतम लॉगिंग मुद्दों, कम कार्डिनैलिटी अनुमानों से सावधान रहें, और याद रखें कि DMLRequestSort
की सेटिंग निष्पादन योजना के हिस्से के रूप में कैश किया गया है।
इस श्रृंखला का अंतिम भाग न्यूनतम लॉगिंग . प्राप्त करने के लिए आवश्यक शर्तों का विवरण देता है RowsetBulk
. का उपयोग किए बिना तंत्र। ये ट्रेस फ्लैग 610 के तहत SQL सर्वर 2008 में जोड़े गए नए सुविधाओं से सीधे मेल खाते हैं, फिर SQL सर्वर 2016 से डिफ़ॉल्ट रूप से चालू होने के लिए बदल दिए जाते हैं।