वृद्धिशील अद्यतन के बाद आँकड़े गायब हो जाते हैं


21

वृद्धिशील आँकड़ों का उपयोग करते हुए हमारे पास एक बड़ा विभाजन SQL सर्वर डेटाबेस है। सभी अनुक्रमणिकाएँ संरेखित हैं। जब हम एक विभाजन को ऑनलाइन फिर से बनाने की कोशिश करते हैं, तो विभाजन के बाद सभी आँकड़े गायब हो जाते हैं।

नीचे SQL Server 2014 में AdventureWorks2014 डेटाबेस के साथ समस्या को दोहराने के लिए एक स्क्रिप्ट है।

--Example against AdventureWorks2014 Database

CREATE PARTITION FUNCTION TransactionRangePF1 (DATETIME)
AS RANGE RIGHT FOR VALUES 
(
   '20130501', '20130601', '20130701', '20130801', 
   '20130901', '20131001', '20131101', '20131201', 
   '20140101', '20140201', '20140301'
);
GO

CREATE PARTITION SCHEME TransactionsPS1 AS PARTITION TransactionRangePF1 TO 
(
  [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], 
  [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], 
  [PRIMARY], [PRIMARY], [PRIMARY]
);
GO

CREATE TABLE dbo.TransactionHistory 
(
  TransactionID        INT      NOT NULL, -- not bothering with IDENTITY here
  ProductID            INT      NOT NULL,
  ReferenceOrderID     INT      NOT NULL,
  ReferenceOrderLineID INT      NOT NULL DEFAULT (0),
  TransactionDate      DATETIME NOT NULL DEFAULT (GETDATE()),
  TransactionType      NCHAR(1) NOT NULL,
  Quantity             INT      NOT NULL,
  ActualCost           MONEY    NOT NULL,
  ModifiedDate         DATETIME NOT NULL DEFAULT (GETDATE()),
  CONSTRAINT CK_TransactionType 
    CHECK (UPPER(TransactionType) IN (N'W', N'S', N'P'))
) 
ON TransactionsPS1 (TransactionDate);


INSERT INTO dbo.TransactionHistory
SELECT * FROM Production.TransactionHistory
--  SELECT * FROM sys.partitions
--  WHERE object_id = OBJECT_ID('dbo.TransactionHistory');

CREATE NONCLUSTERED INDEX IDX_ProductId ON dbo.TransactionHistory (ProductId) 
  WITH (DATA_COMPRESSION = ROW, STATISTICS_INCREMENTAL=ON)  
  ON TransactionsPS1 (TransactionDate)

DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
PRINT 'Stats are avialable'  

ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD 
  PARTITION = 9 WITH (ONLINE = ON , DATA_COMPRESSION = ROW)

PRINT 'After online index rebuild by partition stats are now gone'
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);

PRINT 'Rebuild the stats with a rebuild for all paritions (this works)' 
ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD 
  PARTITION = ALL WITH (ONLINE = ON , DATA_COMPRESSION = ROW, 
  STATISTICS_INCREMENTAL = ON)

PRINT 'Stats are back'
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);

PRINT 'Works correctly for an offline rebuild by partition'
ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD 
  PARTITION = 9 WITH (ONLINE = OFF , DATA_COMPRESSION = ROW)

    --stats still there  
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);

ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD 
  PARTITION = 9 WITH (ONLINE = ON , DATA_COMPRESSION = ROW)

DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
PRINT' stats are gone!!!!!!'

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

कृपया मुझे बताएं कि क्या मुझे कुछ याद आ रहा है?

अपडेट:

जहां तक ​​वृद्धिशील आँकड़ों की हमारी आवश्यकता है: हम एक आंतरिक ग्राहक आईडी पर विभाजन कर रहे हैं, न कि किसी तिथि पर। इसलिए जब एक नया क्लाइंट लाया जाता है (डेटा का बड़ा बैक-लोड) तो हम बस विभाजन के लिए आँकड़े अपडेट कर सकते हैं और इस नए ग्राहक के लिए बनाई जा रही किसी भी बदसूरत योजना से जल्दी से बच सकते हैं। मुझे लगता है कि मैं इसे Microsoft के साथ एक बग के रूप में दर्ज करूंगा और देखूंगा कि उन्हें उस विभाजन के आंकड़ों को फिर से नमूना लेने के लिए क्या कहना और जाना है।

बग रिपोर्ट कनेक्ट करें:

वृद्धिशील आँकड़ों के साथ ऑनलाइन सूचकांक के पुनर्निर्माण के बाद आँकड़े गायब हो जाते हैं

अद्यतन: Microsoft ने पुष्टि की है कि यह एक बग है।


1
अद्यतन: Microsoft ने मुझे आज सुबह एक ईमेल भेजा कि यह बग SQL 2014 के लिए अगले CU अपडेट में सही हो जाएगा।
जेसन

क्या आप जानते हैं कि किस CU ने इसे ठीक किया है, या KB क्या है जो उन्होंने उस ईमेल में रिपोर्ट किया है? यह देखने की कोशिश की जा रही है कि यह कब तय किया गया था।
mbourgon

1
बहुत यकीन है कि यह VSTS बग नंबर 8046729 KB आलेख संख्या 3194959 है जो SQL Server 2014 SP1 के लिए CU 9 का एक हिस्सा था। KB का लिंक यहां दिया गया है
जेसन

हाँ, ऐसा लगता है - और यह पिछले महीने 2016SP1 पर तय किया गया था। बहुत बहुत शुक्रिया!
mbourgon

सुधार: 2016 SP1 CU2 में ठीक किया गया। यह 2016 SP1 CU1 पर होता है।
mbourgon

जवाबों:


17

यकीन नहीं है कि यह बग है, प्रति से लेकिन यह निश्चित रूप से एक दिलचस्प घटना है। SQL सर्वर 2014 में ऑनलाइन पार्टीशन नए हैं इसलिए इसके साथ सॉर्ट करने के लिए कुछ इंटर्नल हो सकते हैं।

यहाँ आपके लिए मेरी सबसे अच्छी व्याख्या है। वृद्धिशील आँकड़ों की बिल्कुल आवश्यकता होती है कि सभी विभाजनों को एक ही दर पर नमूना लिया जाए ताकि जब इंजन आँकड़ों के पृष्ठों को मिला दे तो यह आश्वस्त हो सके कि सैंपल वितरण तुलनीय है। REBUILD100% नमूना दर पर आवश्यक डेटा के नमूने। इस बात की कोई गारंटी नहीं है कि विभाजन 9 पर 100% नमूना दर हमेशा विभाजन के बाकी हिस्सों की सटीक नमूना दर होगी। इस वजह से, ऐसा प्रतीत होता है कि इंजन नमूने को मर्ज नहीं कर सकता है और आप खाली आँकड़ों के साथ समाप्त हो जाते हैं। हालाँकि, सांख्यिकी वस्तु अभी भी है:

select 
    check_time = sysdatetime(),                         
    schema_name = sh.name,
    table_name = t.name,
    stat_name = s.name,
    index_name = i.name,
    stats_column = index_col(quotename(sh.name)+'.'+quotename(t.name),s.stats_id,1),
    s.stats_id,
    s.has_filter,                       
    s.is_incremental,
    s.auto_created,
    sp.last_updated,    
    sp.rows,
    sp.rows_sampled,                        
    sp.unfiltered_rows,
    modification_counter 
from sys.stats s 
join sys.tables t 
    on s.object_id = t.object_id
join sys.schemas sh
    on t.schema_id = sh.schema_id
left join sys.indexes i 
    on s.object_id = i.object_id
    and s.name = i.name
outer apply sys.dm_db_stats_properties(s.object_id, s.stats_id) sp
where t.name = 'TransactionHistory' and sh.name = 'dbo'

आप किसी भी माध्यम से बूँद भर सकते हैं:

UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE;

या

UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE ON PARTITIONS (9);

या आप उस ऑब्जेक्ट का उपयोग करके किसी क्वेरी प्लान के पहले संकलन पर अपडेट करने के लिए AutoStats की प्रतीक्षा कर सकते हैं:

-- look at my creative query
select * 
from dbo.TransactionHistory
where TransactionDate = '20140101';

उस सब के बाद, एरिन स्टेलैटो के इस ज्ञानवर्धक पोस्ट ने बताया कि वृद्धिशील आँकड़ों की एक बड़ी कमी के रूप में माना जाने लगा है। उनके विभाजन-स्तरीय डेटा का उपयोग क्वेरी प्लान पीढ़ी में ऑप्टिमाइज़र द्वारा नहीं किया जाता है, वृद्धिशील आँकड़ों के अनुमानित लाभ को कम करता है। तब, वृद्धिशील आँकड़ों का वर्तमान लाभ क्या है? मैं प्रस्तुत करूंगा कि उनकी प्राथमिक उपयोगिता पारंपरिक आंकड़ों की तुलना में उच्चतर दर पर लगातार बड़ी तालिकाओं को नमूना करने की क्षमता में है।

अपने उदाहरण का उपयोग करते हुए, यहां बताया गया है कि चीजें कैसे दिखती हैं:

set statistics time on;

update statistics dbo.TransactionHistory(IDX_ProductId)
with fullscan;

--SQL Server Execution Times:
--  CPU time = 94 ms,  elapsed time = 131 ms.


update statistics dbo.TransactionHistory(IDX_ProductId)
with resample on partitions(2);

 --SQL Server Execution Times:
 --  CPU time = 0 ms,  elapsed time = 5 ms.

drop index IDX_ProductId On dbo.TransactionHistory;

CREATE NONCLUSTERED INDEX IDX_ProductId ON dbo.TransactionHistory (ProductId) 
  WITH (DATA_COMPRESSION = ROW)  
  ON [PRIMARY]

update statistics dbo.TransactionHistory(IDX_ProductId)
with fullscan;

 --SQL Server Execution Times:
 --  CPU time = 76 ms,  elapsed time = 66 ms.

फुलस्कैन आँकड़े वृद्धिशील आँकड़ों पर अद्यतन करते हैं जिनकी लागत 131 मि। फुलस्कैन सांख्यिकी गैर-संरेखित संरेखित लागत 66 एमएस पर अद्यतन करती है। गैर-संरेखित आँकड़ा धीमी गति से ओवरहेड होने के कारण अलग-अलग आँकड़ों के साथ मुख्य हिस्टोग्राम में वापस आ जाता है।। हालांकि, विभाजन-संरेखित सांख्यिकीय ऑब्जेक्ट का उपयोग करके, हम एक विभाजन को अपडेट कर सकते हैं और इसे 5 एमएस में मुख्य हिस्टोग्राम बूँद में विलय कर सकते हैं। तो इस बिंदु पर वृद्धिशील के साथ प्रशासक एक निर्णय के साथ सामना किया है। वे केवल अद्यतनों को अद्यतन करके अपने समग्र सांख्यिकी रखरखाव समय को कम कर सकते हैं, पारंपरिक रूप से अद्यतन करने की आवश्यकता होगी, या वे उच्च नमूना दरों के साथ प्रयोग कर सकते हैं जैसे कि वे संभावित रूप से अपनी पिछली रखरखाव समय सीमा के दौरान समान अवधि में अधिक पंक्तियों का नमूना लेते हैं। पूर्व रखरखाव कक्ष में श्वास कक्ष की अनुमति देता है, बाद वाले एक बहुत बड़ी मेज पर एक जगह पर आंकड़े धक्का दे सकते हैं जहां प्रश्नों को कई सटीक आंकड़ों के आधार पर बेहतर योजना मिलती है। यह कोई गारंटी नहीं है और आपका माइलेज अलग हो सकता है।

पाठक देख सकते हैं कि 66 एमएस इस तालिका पर एक दर्दनाक आँकड़े अद्यतन समय नहीं है, इसलिए मैंने स्टैकएक्सचेंज डेटा सेट पर एक परीक्षण स्थापित करने की कोशिश की। हाल ही में जिस डंप को मैंने डाउनलोड किया उसमें 6,418,608 पोस्ट (2012 से स्टैकऑवरफ्लो पोस्ट और मेरी तरफ से सभी पोस्ट को छोड़कर) हैं।

मैंने डेटा को [CreationDate]इसलिए विभाजित किया है ... डेमो।

यहां कुछ सुंदर मानक परिदृश्यों के लिए कुछ समय दिया गया है (100% - सूचकांक पुनर्निर्माण, डिफ़ॉल्ट - आँकड़े ऑटो-अपडेट या UPDATE STATISTICSएक निर्दिष्ट नमूना दर के बिना:

  • फुलस्कैन के साथ नॉन-इंक्रीमेंटल स्टैटिस्टिक बनाएं: सीपीयू समय = 23500 एमएस, बीता हुआ समय = 22521 एमएस।
  • इंक्रीमेंटल स्टैटिस्टिक वेथ फुलस्कैन बनाएं: सीपीयू समय = 20406 एमएस, बीता हुआ समय = 15413 एमएस।
  • नॉन-इन्क्रीमेंटल स्टैटिस्टिक को डिफॉल्ट सैंपल रेट के साथ अपडेट करें: सीपीयू समय = 406 एमएस, बीता हुआ समय = 408 एमएस।
  • डिफ़ॉल्ट नमूना दर के साथ वृद्धिशील आँकड़ा अपडेट करें: सीपीयू समय = 453 एमएस, बीता हुआ समय = 507 एमएस।

मान लें कि हम इन डिफ़ॉल्ट परिदृश्यों की तुलना में अधिक परिष्कृत हैं और यह तय किया है कि 10% नमूना दर न्यूनतम दर है जो हमें रखरखाव समय को उचित समय सीमा तक रखने के दौरान हमें उन योजनाओं को प्राप्त करना चाहिए जो हमें चाहिए।

  • अद्यतन गैर-वृद्धिशील आँकड़ा 10 प्रतिशत के साथ: सीपीयू समय = 2344 एमएस, बीता समय = 2441 एमएस।
  • 10 प्रतिशत के नमूने के साथ वृद्धिशील आँकड़ा अपडेट करें: सीपीयू समय = 2344 एमएस, बीता हुआ समय = 2388 एमएस।

अब तक एक वृद्धिशील आँकड़ा होने का कोई स्पष्ट लाभ नहीं है। हालाँकि, यदि हम अनिर्दिष्ट sys.dm_db_stats_properties_internal() DMV (नीचे) का लाभ उठाते हैं, तो आप कुछ जानकारी प्राप्त कर सकते हैं कि आप किस विभाजन (अपडेट) में अपडेट करना चाहते हैं। मान लें कि हमने विभाजन 3 में डेटा में बदलाव किए हैं और हम चाहते हैं कि आने वाले प्रश्नों के लिए आँकड़े नए हों। यहाँ हमारे विकल्प हैं:

  • नॉन-इन्क्रीमेंटल को डिफॉल्ट में अपडेट करें (ऑटो-स्टैट्स अपडेट का डिफ़ॉल्ट व्यवहार भी): 408 एमएस।
  • अद्यतन गैर-वृद्धि 10%: 2441 एमएस।
  • अद्यतन वृद्धिशील सांख्यिकी, विभाजन 3 विमोचन (10% - हमारी परिभाषित नमूना दर): सीपीयू समय = 63 एमएस, बीता हुआ समय = 63 एमएस।

यहां हमें निर्णय लेने की आवश्यकता है। क्या हम 63 एमएस की जीत लेते हैं। आँकड़ों का विभाजन-आधारित अद्यतन, या हम नमूना दर को और भी अधिक बढ़ाते हैं? मान लीजिए कि हम वृद्धिशील आँकड़ों पर 50% नमूना लेने की प्रारंभिक इच्छा रखते हैं:

  • 50% पर वृद्धिशील सांख्यिकी अपडेट करें: बीता हुआ समय = 16840 एमएस।
  • अद्यतन वृद्धिशील सांख्यिकी, विभाजन 3 के साथ रीकंप्लस (50% - हमारा नया अपडेट समय): बीता हुआ समय = 295 एमएस।

हम बहुत अधिक डेटा का नमूना लेने में सक्षम हैं, शायद हमारे डेटा के बारे में बेहतर अनुमान लगाने के लिए ऑप्टिमाइज़र की स्थापना कर रहे हैं (भले ही यह विभाजन-स्तरीय आँकड़ों का उपयोग नहीं कर रहा है, फिर भी) और हम इसे और अधिक तेज़ी से करने में सक्षम हैं जो अब हमारे पास है वृद्धिशील सांख्यिकी।

हालांकि यह पता लगाने के लिए एक अंतिम मजेदार बात है। तुल्यकालिक आँकड़े अपडेट के बारे में क्या? जब ऑटोस्टैट्स में किक होती है तब भी 50% नमूना दर संरक्षित होती है?

मैंने विभाजन 3 से डेटा हटा दिया और क्रिएशनडेट पर एक क्वेरी चलाई और फिर उसी क्वेरी के साथ दरों की जाँच की। 50% नमूना दर संरक्षित थी।

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

  • इंडेक्स के साथ बनाए गए आंकड़े जो आधार तालिका के साथ विभाजन-संरेखित नहीं होते हैं।
  • AlwaysOn पठनीय माध्यमिक डेटाबेस पर बनाए गए आँकड़े।
  • रीड-ओनली डेटाबेस पर बनाए गए आंकड़े।
  • फ़िल्टर किए गए अनुक्रमित पर बनाए गए आंकड़े।
  • आंकड़ों को विचारों पर बनाया गया।
  • आंतरिक तालिकाओं पर बनाए गए आँकड़े।
  • स्थानिक इंडेक्स या XML इंडेक्स के साथ बनाए गए आंकड़े।

उम्मीद है की यह मदद करेगा

select 
    sysdatetime(),                          
    schema_name = sh.name,
    table_name = t.name,
    stat_name = s.name,
    index_name = i.name,
    leading_column = index_col(quotename(sh.name)+'.'+quotename(t.name),s.stats_id,1),
    s.stats_id,
    parition_number = isnull(sp.partition_number,1),
    s.has_filter,                       
    s.is_incremental,
    s.auto_created,
    sp.last_updated,    
    sp.rows,
    sp.rows_sampled,                        
    sp.unfiltered_rows,
    modification_counter = coalesce(sp.modification_counter, n1.modification_counter) 
from sys.stats s 
join sys.tables t 
    on s.object_id = t.object_id
join sys.schemas sh
    on t.schema_id = sh.schema_id
left join sys.indexes i 
    on s.object_id = i.object_id
        and s.name = i.name
cross apply sys.dm_db_stats_properties_internal(s.object_id, s.stats_id) sp
outer apply sys.dm_db_stats_properties_internal(s.object_id, s.stats_id) n1
where n1.node_id = 1
    and (
            (is_incremental = 0)
               or
            (is_incremental = 1 and sp.partition_number is not null)
         )
    and t.name = 'Posts'
    and s.name like 'st_posts%'
order by s.stats_id,isnull(sp.partition_number,1)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.