Database
 sql >> डेटाबेस >  >> RDS >> Database

INSERT के साथ न्यूनतम लॉगिंग… चयन करें और फास्ट लोड संदर्भ

यह पोस्ट नई जानकारी provides प्रदान करती है न्यूनतम रूप से लॉग किए गए बल्क लोड . के लिए पूर्व शर्त के बारे में INSERT...SELECT . का उपयोग करते समय अनुक्रमित तालिकाओं . में ।

इन मामलों को सक्षम करने वाली आंतरिक सुविधा को FastLoadContext . कहा जाता है . इसे दस्तावेज़ ट्रेस फ़्लैग 610 का उपयोग करके SQL सर्वर 2008 से 2014 तक सक्रिय किया जा सकता है। SQL सर्वर 2016 से आगे, FastLoadContext डिफ़ॉल्ट रूप से सक्षम है; ट्रेस ध्वज की आवश्यकता नहीं है।

बिना FastLoadContext . के , एकमात्र इंडेक्स इंसर्ट जो न्यूनतम लॉग किया जा सकता है क्या वे खाली . में हैं द्वितीयक अनुक्रमणिका के बिना संकुल अनुक्रमणिका, जैसा कि इस श्रृंखला के भाग दो में शामिल किया गया है। न्यूनतम लॉगिंग अनइंडेक्स्ड हीप टेबल के लिए शर्तों को पहले भाग में शामिल किया गया था।

अधिक पृष्ठभूमि के लिए, डेटा प्रदर्शन लोडिंग मार्गदर्शिका और टाइगर टीम देखें SQL सर्वर 2016 के लिए व्यवहार परिवर्तन पर नोट्स।

फास्ट लोड प्रसंग

एक त्वरित अनुस्मारक के रूप में, RowsetBulk सुविधा (भाग 1 और 2 में शामिल) न्यूनतम रूप से लॉग किए गए . को सक्षम करती है इसके लिए बल्क लोड:

  • खाली और खाली नहीं ढेर के साथ टेबल:
    • टेबल लॉकिंग; और
    • कोई द्वितीयक अनुक्रमणिका नहीं।
  • खाली संकुल तालिकाएं , साथ:
    • टेबल लॉकिंग; और
    • कोई द्वितीयक अनुक्रमणिका नहीं; और
    • DMLRequestSort=true क्लस्टर इंडेक्स इंसर्ट . पर ऑपरेटर।

FastLoadContext कोड पथ न्यूनतम लॉग किए गए . के लिए समर्थन जोड़ता है और समवर्ती बल्क लोड चालू:

  • खाली और गैर-रिक्त क्लस्टर किए गए बी-ट्री इंडेक्स।
  • खाली और गैर-रिक्त गैर-संकुल एक समर्पित . द्वारा अनुरक्षित b-पेड़ अनुक्रमणिका इंडेक्स इंसर्ट योजना संचालक।

FastLoadContext DMLRequestSort=true की भी आवश्यकता है सभी मामलों में संबंधित योजना ऑपरेटर पर।

आपने RowsetBulk . के बीच एक ओवरलैप देखा होगा और FastLoadContext बिना सेकेंडरी इंडेक्स वाली खाली क्लस्टर टेबल के लिए। एक TABLOCK संकेत आवश्यक नहीं है FastLoadContext . के साथ , लेकिन यह अनुपस्थित होना आवश्यक नहीं है या। परिणामस्वरूप, TABLOCK . के साथ एक उपयुक्त इंसर्ट अभी भी न्यूनतम लॉगिंग के लिए योग्य हो सकता है FastLoadContext . के माध्यम से अगर यह विस्तृत RowsetBulk . में विफल रहता है परीक्षण।

FastLoadContext अक्षम किया जा सकता है SQL सर्वर 2016 पर प्रलेखित ट्रेस ध्वज 692 का उपयोग कर। डिबग चैनल विस्तारित घटना fastloadcontext_enabled FastLoadContext की निगरानी के लिए इस्तेमाल किया जा सकता है प्रति अनुक्रमणिका विभाजन (रोसेट) का उपयोग। यह इवेंट RowsetBulk . के लिए सक्रिय नहीं होता है भार।

मिश्रित लॉगिंग

एक ही INSERT...SELECT FastLoadContext . का उपयोग करके कथन पूरी तरह से लॉग कर सकते हैं न्यूनतम लॉगिंग . के दौरान कुछ पंक्तियां अन्य।

पंक्तियाँ डाली जाती हैं एक बार में एक इंडेक्स इंसर्ट . द्वारा ऑपरेटर और पूरी तरह से लॉग इन निम्नलिखित मामलों में:

  • सभी पंक्तियों को पहले . में जोड़ा गया इंडेक्स पेज, अगर इंडेक्स खाली था ऑपरेशन की शुरुआत में।
  • पंक्तियों को मौजूदा में जोड़ा गया अनुक्रमणिका पृष्ठ।
  • पंक्तियां स्थानांतरित पृष्ठों के बीच एक पृष्ठ विभाजन द्वारा।

अन्यथा, आदेशित सम्मिलित स्ट्रीम से पंक्तियाँ एक बिल्कुल नए पृष्ठ . में जोड़ दी जाती हैं एक अनुकूलित, और न्यूनतम लॉग किए गए . का उपयोग करके कोड पथ। एक बार नए पृष्ठ पर जितनी संभव हो उतनी पंक्तियाँ लिखी जाती हैं, तो यह सीधे मौजूदा लक्ष्य सूचकांक संरचना से जुड़ जाती है।

नया जोड़ा गया पेज जरूरी नहीं . होगा पूर्ण हो (हालांकि स्पष्ट रूप से यह आदर्श मामला है) क्योंकि SQL सर्वर को सावधान रहना होगा कि नए पृष्ठ पर पंक्तियों को न जोड़ें जो तार्किक रूप से मौजूदा से संबंधित हैं सूचकांक पेज। नया पृष्ठ एक इकाई के रूप में सूचकांक में 'सिलाई' किया जाएगा, इसलिए हमारे पास नए पृष्ठ पर ऐसी कोई पंक्तियाँ नहीं हो सकतीं जो कहीं और से संबंधित हों। भीतर rows पंक्तियों को जोड़ते समय यह मुख्य रूप से एक समस्या है इंडेक्स की मौजूदा कुंजी श्रेणी, प्रारंभ से पहले या मौजूदा अनुक्रमणिका कुंजी श्रेणी के अंत के बाद के बजाय।

यह अभी भी संभव है अंदर . में नए पृष्ठ जोड़ने के लिए मौजूदा अनुक्रमणिका कुंजी श्रेणी, लेकिन नई पंक्तियों को पूर्ववर्ती पर उच्चतम कुंजी से ऊपर क्रमबद्ध करना चाहिए मौजूदा अनुक्रमणिका पृष्ठ और निम्नलिखित . पर निम्नतम कुंजी से नीचे क्रमबद्ध करें मौजूदा सूचकांक पृष्ठ। न्यूनतम लॉगिंग achieving प्राप्त करने के सर्वोत्तम अवसर के लिए इन परिस्थितियों में, सुनिश्चित करें कि सम्मिलित पंक्तियाँ जहाँ तक संभव हो मौजूदा पंक्तियों के साथ ओवरलैप न हों।

DMLRequestSort शर्तें

याद रखें कि FastLoadContext केवल तभी सक्रिय किया जा सकता है जब DMLRequestSort सत्य . पर सेट है संबंधित इंडेक्स इंसर्ट . के लिए निष्पादन योजना में ऑपरेटर।

दो मुख्य कोड पथ हैं जो DMLRequestSort . सेट कर सकते हैं करने के लिए सच सूचकांक डालने के लिए। कोई भी रास्ता लौट रहा है सच पर्याप्त है।

1. FOptimizeInsert

sqllang!CUpdUtil::FOptimizeInsert कोड की आवश्यकता है:

  • 250 से अधिक पंक्तियां अनुमानित डाला जाना; और
  • 2 से अधिक पृष्ठ अनुमानित डेटा आकार डालें; और
  • लक्ष्य अनुक्रमणिका 3 से कम पत्ती वाले पृष्ठ . होने चाहिए ।

ये शर्तें RowsetBulk . जैसी ही हैं एक खाली क्लस्टर इंडेक्स पर, दो से अधिक इंडेक्स लीफ-लेवल पेजों के लिए अतिरिक्त आवश्यकता नहीं है। ध्यान से नोट करें कि यह मौजूदा अनुक्रमणिका . के आकार को दर्शाता है डालने से पहले, नहीं जोड़े जाने वाले डेटा का अनुमानित आकार।

नीचे दी गई स्क्रिप्ट इस श्रृंखला में पहले के हिस्सों में इस्तेमाल किए गए डेमो का एक संशोधन है। यह न्यूनतम लॉगिंग . दिखाता है जब तीन से कम अनुक्रमणिका पृष्ठ पहले . भर जाते हैं परीक्षण INSERT...SELECT रन। परीक्षण तालिका स्कीमा ऐसा है कि डेटाबेस के लिए पंक्ति संस्करण बंद होने पर 130 पंक्तियाँ एकल 8KB पृष्ठ पर फ़िट हो सकती हैं। पहले TOP . में गुणक मौजूदा इंडेक्स पेजों की संख्या पहले . निर्धारित करने के लिए क्लॉज को बदला जा सकता है परीक्षण INSERT...SELECT निष्पादित किया जाता है:

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
-- 130 rows per page for this table 
-- structure with row versioning off
INSERT dbo.Test
    (c1)
SELECT TOP (3 * 130)    -- Change the 3 here
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV;
GO
-- Show physical index statistics
-- to confirm the number of pages
SELECT
    DDIPS.index_type_desc,
    DDIPS.alloc_unit_type_desc,
    DDIPS.page_count,
    DDIPS.record_count,
    DDIPS.avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats
(
    DB_ID(), 
    OBJECT_ID(N'dbo.Test', N'U'), 
    1,      -- Index ID
    NULL,   -- Partition ID
    'DETAILED'
) AS DDIPS
WHERE
    DDIPS.index_level = 0;  -- leaf level only
GO
-- Clear the plan cache
DBCC FREEPROCCACHE;
GO
-- Clear the log
CHECKPOINT;
GO
-- Main test
INSERT dbo.Test
    (c1)
SELECT TOP (269)
    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)';
GO

जब संकुल अनुक्रमणिका 3 पृष्ठों के साथ पहले से लोड हो जाती है , परीक्षण प्रविष्टि पूरी तरह से लॉग है (संक्षिप्तता के लिए छोड़े गए लेनदेन लॉग विवरण रिकॉर्ड):

जब तालिका केवल 1 या 2 पृष्ठों के साथ पहले से लोड हो जाती है , परीक्षण सम्मिलन न्यूनतम लॉग किया गया . है :

जब तालिका प्रीलोडेड नहीं है किसी भी पृष्ठ के साथ, परीक्षण भाग दो से खाली क्लस्टर तालिका डेमो चलाने के बराबर है, लेकिन बिना TABLOCK संकेत:

पहली 130 पंक्तियाँ पूरी तरह से लॉग की गई हैं . ऐसा इसलिए है क्योंकि हमारे शुरू होने से पहले सूचकांक खाली था, और 130 पंक्तियाँ पहले पृष्ठ पर फिट होती हैं। याद रखें, पहला पेज हमेशा पूरी तरह लॉग होता है जब FastLoadContext का उपयोग किया जाता है और सूचकांक पहले से खाली था। शेष 139 पंक्तियों को न्यूनतम लॉगिंग . के साथ सम्मिलित किया गया है ।

अगर कोई TABLOCK इंसर्ट में हिंट जोड़ा जाता है, सभी पेज कम से कम लॉग किए गए हैं (पहले वाले सहित) क्योंकि खाली क्लस्टर इंडेक्स लोड अब RowsetBulk के लिए योग्य है तंत्र (Sch-M . लेने की कीमत पर) ताला)।

2. FDemandRowsSortedForPerformance

अगर FOptimizeInsert परीक्षण विफल, DMLRequestSort अभी भी सत्य . पर सेट किया जा सकता है sqllang!CUpdUtil::FDemandRowsSortedForPerformance में परीक्षणों के दूसरे सेट द्वारा कोड। ये शर्तें थोड़ी अधिक जटिल हैं, इसलिए कुछ मापदंडों को परिभाषित करना उपयोगी होगा:

  • Pमौजूदा पत्ती-स्तरीय पृष्ठों . की संख्या लक्षित अनुक्रमणिका . में ।
  • I - अनुमानित सम्मिलित करने के लिए पंक्तियों की संख्या।
  • R =P / I (प्रत्येक सम्मिलित पंक्ति के लिए लक्षित पृष्ठ)।
  • T - लक्ष्य विभाजन की संख्या (विभाजित के लिए 1)।

DMLRequestSort . का मान निर्धारित करने का तर्क तब है:

  • यदि P <= 16 वापसी झूठी , अन्यथा :
    • यदि R < 8 :
      • यदि P > 524 वापसी सत्य , अन्यथा गलत
    • यदि R >= 8 :
      • अगर T > 1 और I > 250 वापसी सत्य , अन्यथा गलत

उपरोक्त परीक्षणों का मूल्यांकन योजना संकलन के दौरान क्वेरी प्रोसेसर द्वारा किया जाता है। एक अंतिम शर्त है स्टोरेज इंजन कोड द्वारा मूल्यांकन किया गया (IndexDataSetSession::WakeUpInternal ) निष्पादन के समय:

  • DMLRequestSort वर्तमान में सत्य है; और
  • I >= 100

हम इस सारे तर्क को आगे प्रबंधनीय टुकड़ों में तोड़ देंगे।

16 से अधिक मौजूदा लक्ष्य पृष्ठ

पहला परीक्षण P <= 16 इसका मतलब है कि 17 से कम मौजूदा लीफ पेज वाले इंडेक्स FastLoadContext . के लिए योग्य नहीं होंगे इस कोड पथ के माध्यम से। इस बिंदु पर बिल्कुल स्पष्ट होने के लिए, P पहले . लक्ष्य अनुक्रमणिका में लीफ़-स्तरीय पृष्ठों की संख्या है INSERT...SELECT निष्पादित किया जाता है।

तर्क के इस भाग को प्रदर्शित करने के लिए, हम परीक्षण संकुल तालिका को 16 पृष्ठों . के साथ पहले से लोड करेंगे आंकड़े का। इसके दो महत्वपूर्ण प्रभाव हैं (याद रखें कि दोनों कोड पथ गलत लौटना चाहिए एक गलत . के साथ समाप्त करने के लिए DMLRequestSort . के लिए मान ):

  1. यह सुनिश्चित करता है कि पिछला FOptimizeInsert परीक्षण विफल , क्योंकि तीसरी शर्त पूरी नहीं हुई है (P < 3 )।
  2. P <= 16 FDemandRowsSortedForPerformance . में स्थिति नहीं भी होगा मिलना चाहिए।

इसलिए हम उम्मीद करते हैं FastLoadContext सक्षम नहीं होना है। संशोधित डेमो स्क्रिप्ट है:

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
-- 130 rows per page for this table 
-- structure with row versioning off
INSERT dbo.Test
    (c1)
SELECT TOP (16 * 130) -- 16 pages
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV;
GO
-- Show physical index statistics
-- to confirm the number of pages
SELECT
    DDIPS.index_type_desc,
    DDIPS.alloc_unit_type_desc,
    DDIPS.page_count,
    DDIPS.record_count,
    DDIPS.avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats
(
    DB_ID(), 
    OBJECT_ID(N'dbo.Test', N'U'), 
    1,      -- Index ID
    NULL,   -- Partition ID
    'DETAILED'
) AS DDIPS
WHERE
    DDIPS.index_level = 0;  -- leaf level only
GO
-- Clear the plan cache
DBCC FREEPROCCACHE;
GO
-- Clear the log
CHECKPOINT;
GO
-- Main test
INSERT dbo.Test
    (c1)
SELECT TOP (269)
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV1
CROSS JOIN master.dbo.spt_values AS SV2;
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)';

सभी 269 पंक्तियाँ पूरी तरह से लॉग हैं भविष्यवाणी के अनुसार:

ध्यान दें कि हम सम्मिलित करने के लिए नई पंक्तियों की संख्या कितनी भी अधिक क्यों न सेट करें, ऊपर दी गई स्क्रिप्ट कभी नहीं होगी न्यूनतम लॉगिंग उत्पन्न करें P <= 16 . के कारण परीक्षण (और P < 3 FOptimizeInsert . में परीक्षण करें )।

यदि आप बड़ी संख्या में पंक्तियों के साथ स्वयं डेमो चलाना चुनते हैं, तो उस अनुभाग पर टिप्पणी करें जो व्यक्तिगत लेनदेन लॉग रिकॉर्ड दिखाता है, अन्यथा आप बहुत लंबे समय तक प्रतीक्षा करेंगे, और SSMS क्रैश हो सकता है। (निष्पक्ष होने के लिए, यह वैसे भी ऐसा कर सकता है, लेकिन जोखिम में क्यों जोड़ें।)

पृष्ठ प्रति सम्मिलित पंक्ति अनुपात

यदि 17 या अधिक . हैं तो मौजूदा इंडेक्स में लीफ पेज, पिछला P <= 16 परीक्षण विफल नहीं होगा। तर्क का अगला भाग मौजूदा पृष्ठों . के अनुपात से संबंधित है नई सम्मिलित पंक्तियों . के लिए . इसे न्यूनतम लॉगिंग . प्राप्त करने के लिए भी पास करना होगा . एक अनुस्मारक के रूप में, प्रासंगिक शर्तें हैं:

  • अनुपात R =P / I
  • यदि R < 8 :
    • यदि P > 524 वापसी सत्य , अन्यथा गलत

हमें कम से कम 100 पंक्तियों के लिए अंतिम भंडारण इंजन परीक्षण भी याद रखना चाहिए:

  • I >= 100

उन शर्तों को थोड़ा सा पुनर्व्यवस्थित करना, सभी निम्नलिखित में से सत्य होना चाहिए:

  1. P > 524 (मौजूदा इंडेक्स पेज)
  2. I >= 100 (अनुमानित सम्मिलित पंक्तियाँ)
  3. P / I < 8 (अनुपात R )

उन तीन शर्तों को एक साथ पूरा करने के कई तरीके हैं। आइए P . के लिए न्यूनतम संभव मान चुनें (525) और I (100) एक R दे रहा है (525/100) का मान =5.25। यह संतुष्ट करता है (R < 8 परीक्षण), इसलिए हम उम्मीद करते हैं कि इस संयोजन का परिणाम न्यूनतम लॉगिंग . होगा :

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
-- 130 rows per page for this table 
-- structure with row versioning off
INSERT dbo.Test
    (c1)
SELECT TOP (525 * 130) -- 525 pages
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV1
CROSS JOIN master.dbo.spt_values AS SV2;
GO
-- Show physical index statistics
-- to confirm the number of pages
SELECT
    DDIPS.index_type_desc,
    DDIPS.alloc_unit_type_desc,
    DDIPS.page_count,
    DDIPS.record_count,
    DDIPS.avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats
(
    DB_ID(), 
    OBJECT_ID(N'dbo.Test', N'U'), 
    1,      -- Index ID
    NULL,   -- Partition ID
    'DETAILED'
) AS DDIPS
WHERE
    DDIPS.index_level = 0;  -- leaf level only
GO
-- Clear the plan cache
DBCC FREEPROCCACHE;
GO
-- Clear the log
CHECKPOINT;
GO
-- Main test
INSERT dbo.Test
    (c1)
SELECT TOP (100)
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV1
CROSS JOIN master.dbo.spt_values AS SV2;
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)';

100-पंक्ति INSERT...SELECT वास्तव में न्यूनतम लॉग किया गया है :

अनुमानित . को कम करना 99 में पंक्तियाँ डाली गईं (I >= 100 को तोड़ते हुए ), और/या मौजूदा अनुक्रमणिका पृष्ठों की संख्या को घटाकर 524 कर दें (P > 524 . को तोड़कर) ) परिणाम पूर्ण लॉगिंग . में होता है . हम ऐसे बदलाव भी कर सकते हैं जैसे R पूर्ण लॉगिंग produce उत्पन्न करने के लिए अब 8 से कम नहीं है . उदाहरण के लिए, P = 1000 setting सेट करना और I = 125 देता है R = 8 , निम्नलिखित परिणामों के साथ:

डाली गई 125 पंक्तियां पूरी तरह से लॉग थीं जैसा सोचा था। (यह प्रथम पृष्ठ पूर्ण लॉगिंग के कारण नहीं है, क्योंकि अनुक्रमणिका पहले से खाली नहीं थी।)

विभाजित अनुक्रमणिका के लिए पृष्ठ अनुपात

यदि पिछले सभी परीक्षण विफल हो जाते हैं, तो शेष एक परीक्षण के लिए R >= 8 . की आवश्यकता होती है और केवल . कर सकते हैं विभाजनों की संख्या (T .) होने पर संतुष्ट रहें ) 1 और . से बड़ा है 250 से अधिक अनुमानित . हैं सम्मिलित पंक्तियाँ (I ) याद करें:

  • यदि R >= 8 :
    • अगर T > 1 और I > 250 वापसी सत्य , अन्यथा गलत

एक सूक्ष्मता:विभाजित . के लिए अनुक्रमणिका, नियम जो कहता है कि सभी प्रथम-पृष्ठ पंक्तियाँ पूरी तरह से लॉग हैं (शुरुआत में खाली अनुक्रमणिका के लिए) प्रति विभाजन लागू होता है . 15,000 विभाजन वाले ऑब्जेक्ट के लिए, इसका मतलब है कि 15,000 पूरी तरह से लॉग किए गए 'पहले' पृष्ठ।

सारांश और अंतिम विचार

मुख्य भाग में वर्णित मूल्यांकन के सूत्र और क्रम डिबगर का उपयोग करके कोड निरीक्षण पर आधारित होते हैं। उन्हें एक ऐसे रूप में प्रस्तुत किया गया जो वास्तविक कोड में उपयोग किए गए समय और क्रम का बारीकी से प्रतिनिधित्व करता है।

न्यूनतम लॉगिंग के लिए व्यावहारिक आवश्यकताओं का अधिक संक्षिप्त सारांश तैयार करने के लिए, उन स्थितियों को थोड़ा सा पुन:व्यवस्थित और सरल बनाना संभव है INSERT...SELECT . का उपयोग करके बी-पेड़ में डालने पर . नीचे दिए गए परिष्कृत भाव निम्नलिखित तीन मापदंडों का उपयोग करते हैं:

  • P =मौजूदा . की संख्या इंडेक्स लीफ-लेवल पेज.
  • I =अनुमानित सम्मिलित करने के लिए पंक्तियों की संख्या।
  • S =अनुमानित 8KB पृष्ठों में डेटा आकार डालें।

रोसेट बल्क लोड

  • sqlmin!RowsetBulk का उपयोग करता है ।
  • एक खाली की आवश्यकता है TABLOCK . के साथ संकुल अनुक्रमणिका लक्ष्य (या समकक्ष)।
  • आवश्यकता है DMLRequestSort = true क्लस्टर इंडेक्स इंसर्ट . पर ऑपरेटर।
  • DMLRequestSort सेट है true अगर I > 250 और S > 2
  • सम्मिलित सभी पंक्तियां न्यूनतम रूप से लॉग की गई हैं
  • एक Sch-M लॉक समवर्ती टेबल एक्सेस को रोकता है।

तेज़ लोड प्रसंग

  • sqlmin!FastLoadContext का उपयोग करता है ।
  • सक्षम करता हैन्यूनतम लॉग किया हुआ बी-ट्री इंडेक्स में सम्मिलित करता है:
    • संकुलित या गैर संकुलित।
    • टेबल लॉक के साथ या बिना।
    • लक्ष्य अनुक्रमणिका खाली है या नहीं।
  • आवश्यकता है DMLRequestSort = true संबंधित इंडेक्स इंसर्ट . पर योजना संचालक।
  • ब्रांड के लिए लिखी गई केवल पंक्तियाँ नए पृष्ठ बल्क लोडेड हैं और न्यूनतम रूप से लॉग किए गए हैं
  • पहला पृष्ठ पहले के खाली अनुक्रमणिका . का विभाजन हमेशा पूरी तरह से लॉग होता है
  • पूर्ण न्यूनतम I >= 100
  • SQL सर्वर 2016 से पहले ट्रेस ध्वज 610 की आवश्यकता है।
  • SQL सर्वर 2016 से डिफ़ॉल्ट रूप से उपलब्ध (ट्रेस ध्वज 692 अक्षम करता है)।

DMLRequestSort सेट है true के लिए:

  • कोई भी अनुक्रमणिका (विभाजित या नहीं) यदि:
    • I > 250 और P < 3 और S > 2; या
    • I >= 100 और P > 524 और P < I * 8

केवल विभाजित अनुक्रमणिका . के लिए (> 1 विभाजन के साथ), DMLRequestSort true . भी सेट किया गया है अगर:

  • I > 250 और P > 16 और P >= I * 8

उन FastLoadContext . से कुछ दिलचस्प मामले सामने आ रहे हैं शर्तें:

  • सभी एक गैर-विभाजित . में सम्मिलित करता है 3 और 524 के बीच . के साथ अनुक्रमणिका (समावेशी) मौजूदा लीफ पेज पूरी तरह से लॉग हो जाएंगे जोड़े गए पंक्तियों की संख्या और कुल आकार की परवाह किए बिना। यह छोटे (लेकिन खाली नहीं) टेबल पर बड़े इंसर्ट को सबसे ज्यादा प्रभावित करेगा।
  • सभी विभाजित . में सम्मिलित करता है 3 और 16 . के बीच अनुक्रमणिका मौजूदा पृष्ठ पूरी तरह से लॉग होंगे ।
  • बड़ी प्रविष्टियां बड़े पैमाने पर गैर-विभाजित अनुक्रमणिका न्यूनतम रूप से लॉग नहीं हो सकतीं असमानता के कारण P < I * 8 . जब P बड़ा है, एक संगत रूप से बड़ा अनुमानित सम्मिलित पंक्तियों की संख्या (I ) आवश्यक है। उदाहरण के लिए, 8 मिलियन पृष्ठों वाली अनुक्रमणिका न्यूनतम लॉगिंग . का समर्थन नहीं कर सकती है 1 मिलियन या उससे कम पंक्तियाँ सम्मिलित करते समय।

गैर-संकुल अनुक्रमणिका

डेमो में क्लस्टर किए गए इंडेक्स पर लागू समान विचार और गणना गैर-क्लस्टर किए गए पर लागू होते हैं बी-ट्री इंडेक्स भी, जब तक कि इंडेक्स एक समर्पित योजना ऑपरेटर द्वारा बनाए रखा जाता है (एक चौड़ा , या प्रति-सूचकांक योजना)। बेस टेबल ऑपरेटर द्वारा अनुरक्षित गैर-संकुल अनुक्रमणिका (उदा. संकुल अनुक्रमणिका सम्मिलित करें ) FastLoadContext . के लिए योग्य नहीं हैं ।

ध्यान दें कि प्रत्येक गैर-संकुल . के लिए सूत्र पैरामीटर का नए सिरे से मूल्यांकन करने की आवश्यकता है इंडेक्स ऑपरेटर — परिकलित पंक्ति आकार, मौजूदा इंडेक्स पेजों की संख्या, और कार्डिनैलिटी अनुमान।

सामान्य टिप्पणियां

कम कार्डिनैलिटी अनुमान . से सावधान रहें इंडेक्स इंसर्ट . पर ऑपरेटर, क्योंकि ये I . को प्रभावित करेंगे और S पैरामीटर। यदि कार्डिनैलिटी अनुमान त्रुटि के कारण थ्रेशोल्ड तक नहीं पहुंचा जाता है, तो इंसर्ट पूरी तरह से लॉग हो जाएगा ।

याद रखें कि DMLRequestSort योजना के साथ संचित है - पुन:उपयोग की गई योजना के प्रत्येक निष्पादन पर इसका मूल्यांकन नहीं किया जाता है। यह प्रसिद्ध पैरामीटर संवेदनशीलता समस्या (जिसे "पैरामीटर सूँघने" के रूप में भी जाना जाता है) का एक रूप पेश कर सकता है।

P . का मान (इंडेक्स लीफ पेज) रीफ्रेश नहीं है प्रत्येक कथन की शुरुआत में। वर्तमान कार्यान्वयन पूरे बैच . के मान को संचित करता है . इसके अप्रत्याशित दुष्प्रभाव हो सकते हैं। उदाहरण के लिए, एक TRUNCATE TABLE उसी बैच . में एक INSERT...SELECT . के रूप में रीसेट नहीं होगा P इस आलेख में वर्णित गणनाओं के लिए शून्य करने के लिए — वे पूर्व-छंटनी मूल्य का उपयोग करना जारी रखेंगे, और एक पुनर्संकलन मदद नहीं करेगा। अलग-अलग बैचों में बड़े बदलाव सबमिट करना एक समाधान है।

ट्रेस फ़्लैग्स

FDemandRowsSortedForPerformance . को बाध्य करना संभव है सत्य पर लौटने के लिए अदस्तावेजीकृत और असमर्थित . सेट करके ट्रेस फ्लैग 2332, जैसा कि मैंने डेटा बदलने वाले टी-एसक्यूएल प्रश्नों को ऑप्टिमाइज़ करने में लिखा था। जब TF 2332 सक्रिय होता है, तो प्रस्तुत करने के लिए अनुमानित पंक्तियों की संख्या अभी भी कम से कम 100 . होना चाहिए . TF 2332 न्यूनतम लॉगिंग . को प्रभावित करता है FastLoadContext . के लिए निर्णय केवल (यह DMLRequestSort के रूप में विभाजित ढेर के लिए प्रभावी है) संबंधित है, लेकिन इसका ढेर पर कोई प्रभाव नहीं पड़ता है, क्योंकि FastLoadContext केवल अनुक्रमणिका पर लागू होता है)।

एक विस्तृत/प्रति-सूचकांक गैर-संकुल अनुक्रमणिका रखरखाव के लिए योजना आकार को ट्रेस फ़्लैग 8790 (आधिकारिक रूप से प्रलेखित नहीं है, लेकिन एक नॉलेज बेस आलेख में उल्लेख किया गया है और साथ ही मेरे लेख में TF2332 के लिए लिंक किया गया है) का उपयोग करके रोस्टोर टेबल के लिए मजबूर किया जा सकता है।

संबंधित पठन

SQL सर्वर टीम से सुनील अग्रवाल द्वारा सभी:

  • थोक आयात अनुकूलन क्या हैं?
  • थोक आयात अनुकूलन (न्यूनतम लॉगिंग)
  • SQL Server 2008 में न्यूनतम लॉगिंग परिवर्तन
  • SQL Server 2008 (भाग-2) में न्यूनतम लॉगिंग परिवर्तन
  • SQL Server 2008 (भाग-3) में न्यूनतम लॉगिंग परिवर्तन

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. एसक्यूएल चयन करें

  2. हैश क्या? हैश इंडेक्स को समझना

  3. लॉकिंग और प्रदर्शन

  4. SQL में एक रो को कैसे डिलीट करें

  5. यूनियन सभी अनुकूलन