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

sp_updatestats से बचने का एक और कारण

मैंने पहले इस बारे में ब्लॉग किया है कि मुझे sp_updatestats पसंद क्यों नहीं है। मुझे हाल ही में एक और कारण मिला कि यह मेरा दोस्त नहीं है। TL;DR:यह अनुक्रमित दृश्यों पर आंकड़े अपडेट नहीं करता है। अब, दस्तावेज़ीकरण यह दावा नहीं करता कि यह करता है, इसलिए यहां कोई बग नहीं है। MSDN दस्तावेज़ स्पष्ट रूप से बताता है:

वर्तमान डेटाबेस में सभी उपयोगकर्ता-परिभाषित और आंतरिक तालिकाओं के विरुद्ध अद्यतन आँकड़े चलाता है।

लेकिन... आप में से कितने लोगों ने अपने अनुक्रमित विचारों के बारे में सोचा और सोचा कि क्या वे अपडेट हो गए हैं? मैं मानता हूँ मैंने नहीं किया। मैं अनुक्रमित विचारों के बारे में भूल जाता हूं, जो दुर्भाग्यपूर्ण है क्योंकि उचित रूप से उपयोग किए जाने पर वे वास्तव में शक्तिशाली हो सकते हैं। जब आप समस्या निवारण कर रहे हों तो वे एक दुःस्वप्न भी हो सकते हैं, लेकिन मैं आज उनके उपयोग पर बहस नहीं करने जा रहा हूं। मैं बस इतना चाहता हूं कि आप इस बात से अवगत रहें कि वे sp_updatestats द्वारा अपडेट नहीं होते हैं, और देखें कि आपके पास क्या विकल्प हैं।

सेटअप

चूंकि विश्व श्रृंखला अभी समाप्त हुई है, हम अपने परीक्षण के लिए बेसबॉल डेटाबेस का उपयोग करने जा रहे हैं। आप इसे SQLskills Resources पेज से डाउनलोड कर सकते हैं। एक बार बहाल हो जाने पर हम dbo.PlayerInfo नाम की dbo.Players तालिका की एक प्रति बनाएँगे, उसमें कुछ हज़ार पंक्तियाँ लोड करें, और फिर एक अनुक्रमित दृश्य बनाएँ जो हमारी नई तालिका को पिचिंगपोस्ट तालिका से जोड़ता है:

 उपयोग [बेसबॉलडेटा]; टेबल बनाएं [डीबीओ]। 10) न्यूल डिफॉल्ट (नल), [होफिड] [वर्कर] (10) न्यूल डिफॉल्ट (नल), [जन्म वर्ष] [इंट] न्यूल डिफॉल्ट (नल), [जन्म महीने] [इंट] न्यूल डिफॉल्ट (नल), [जन्मदिन] [इंट] न्यूल डिफॉल्ट (नल), [बर्थकंट्री] [वर्कर] (50) न्यूल डिफॉल्ट (नल), [बर्थस्टेट] [वर्कर] (2) न्यूल डिफॉल्ट (नल), [बर्थसिटी] [वर्कर] (50) न्यूल डिफॉल्ट (नल), [मृत्यु वर्ष] [int] पूर्ण डिफ़ॉल्ट (शून्य), [मृत्यु माह] [int] पूर्ण डिफ़ॉल्ट (नल), [मृत्यु दिवस] [int] पूर्ण डिफ़ॉल्ट (नल), [मृत्यु देश] [वर्कर] (50) शून्य डिफॉल्ट (नल), [डेथस्टेट] [वर्कर] (2) न्यूल डिफॉल्ट (नल), [डेथसिटी] [वर्कर] (50) न्यूल डिफॉल्ट (नल), [नाम फर्स्ट] [वर्कर] (50) न्यूल डिफॉल्ट (नल), [नाम लास्ट] [वर्कर] (50) न्यूल डिफॉल्ट (नल), [नाम नोट] [वर्कर] (255) न्यूल डिफॉल्ट (नल), [नाम दिया गया] [वर्कर] (255) न्यूल डिफॉल्ट (नल), [नामनिक] [वर्कर ](255) पूर्ण डिफ़ॉल्ट (नल), [वजन] [int] शून्य डिफ़ॉल्ट (नल), [ऊंचाई] [int] न्यूल, [चमगादड़] [वर्कर] (1) न्यूल डिफॉल्ट (नल), [फेंकता] [वर्कर] (1) न्यूल डिफॉल्ट (नल), [डेब्यू] [वर्कर]( 10) न्यूल डिफॉल्ट (नल), [फाइनलगेम] [वर्कर] (10) न्यूल डिफॉल्ट (नल), [कॉलेज] [वर्कर] (50) न्यूल डिफॉल्ट (नल), [लहमान 40आईडी] [वर्कर] (9) न्यूल डिफॉल्ट ( NULL), [lahman45ID] [varchar](9) NULL DEFAULT (NULL), [retroID] [varchar](9) NULL DEFAULT (NULL), [holtzID] [varchar](9) NULL DEFAULT (NULL), [bbrefID ] [वर्कर] (9) न्यूल डिफॉल्ट (नल), प्राथमिक कुंजी क्लस्टर ([लाहमानिड] एएससी) [प्राथमिक] पर [प्राथमिक] पर; [डीबीओ] में प्रवेश करें। [प्लेयरइन्फो] ([लाहमानिड], [प्लेयरआईडी] ,[managerID] ,[hofID] ,[birthYear] ,[birthMonth] ,[birthday] ,[birthCountry] ,[birthState] ,[birthCity] ,[deathYear] ,[deathMonth] ,[DeathDay] ,[DeathCountry] ,[ डेथस्टेट], [डेथसिटी], [नाम फर्स्ट], [नाम लास्ट] , [नाम नोट], [नाम गिवेन], [नामनिक], [वजन], [ऊंचाई], [चमगादड़], [फेंकता है], [पहली बार], [फाइनलगेम], [कॉलेज], [लाहमान 40 आईडी], [लहमान 45 आईडी], [ रेट्रोआईडी], [होल्ट्ज़िड], [बीबीआरएफआईडी]) चुनें [लहमानआईडी], [प्लेयर आईडी], [मैनेजरआईडी], [होफआईडी], [जन्म वर्ष], [जन्म माह], [जन्मदिन], [जन्म देश], [जन्म राज्य] , [जन्म शहर ] , [मृत्यु वर्ष], [मृत्यु माह], [मृत्यु दिवस], [मृत्यु देश], [मृत्यु राज्य], [मृत्यु शहर], [नाम प्रथम], [नाम अंतिम], [नाम नोट], [नाम दिया गया], [नामनिक], [वजन], [ऊंचाई], [चमगादड़], [फेंकता है], [पहली बार], [अंतिम गेम], [कॉलेज], [लाहमान 40 आईडी], [लहमान 45 आईडी], [रेट्रोआई डी], [होल्ट्ज़िड], [बीबीआरएफआईडी] [डीबीओ] से। [खिलाड़ी] जहां [लहमानिड] <=10000; क्रिएट व्यू [प्लेयरपोस्ट सीजन] स्कीमबिंडिंगस सेलेक्ट [पी] के साथ। ]। [वर्ष आईडी], [पीपी]। [राउंड], [पीपी]। [टीमआईडी], [पीपी]। [डब्ल्यू], [पीपी]। [एल], [पीपी]। [जी] [डीबीओ] से। [प्लेयरइन्फो] [पी] [डीबीओ] में शामिल हों। [पिचिंगपोस्ट] [पीपी] ऑन [पी]। [प्लेयरआईडी] =[पीपी]। [प्लेयरआईडी]; [PlayerPostSeason] पर [[lahmanID], [yearID], [राउंड]); [PlayerPostSeason] ([nameFirst], [nameLast]) पर गैर-अनुक्रमित अनुक्रमणिका [NCI_PlayerPostSeason_Name] बनाएं;

यदि हम संकुलित और गैर संकुल अनुक्रमितों के आँकड़ों की जाँच करते हैं, तो हम देखते हैं कि वे मौजूद हैं:

STAT_HEADER के साथ
DBCC SHOW_STATISTICS ('PlayerPostSeason', CI_PlayerPostSeason);GODBCC SHOW_STATISTICS ('PlayerPostSeason', NCI_PlayerPostSeason_Name) STAT_HEADER के साथ;GO

प्रारंभिक निर्माण के बाद सूचकांक दृश्य आंकड़े

अब हम PlayerInfo में और पंक्तियां डालेंगे:

[dbo] में
इन्सर्ट करें। जन्म शहर], [मृत्यु वर्ष], [मृत्यु माह], [मृत्यु दिवस], [मृत्यु देश], [मृत्यु राज्य], [मृत्यु शहर], [नाम प्रथम], [नाम अंतिम], [नाम नोट], [नाम दिया गया], [नाम निक], [वजन] ,[ऊंचाई] ,[चमगादड़] ,[फेंकना] ,[पहली बार] ,[फाइनलगेम] ,[कॉलेज] ,[lahman40ID] ,[lahman45ID] ,[retroID] ,[holtzID] ,[bbrefID]) चुनें [lahmanID] , [खिलाड़ी आईडी], [प्रबंधक आईडी], [होफिड], [जन्म वर्ष], [जन्म महीने], [जन्मदिन], [जन्म देश], [जन्म राज्य], [जन्म शहर] , [मृत्यु वर्ष], [मृत्यु माह], [मृत्यु दिवस], [मृत्यु देश], [मृत्यु राज्य], [मृत्यु शहर], [नाम प्रथम], [नाम अंतिम], [नाम नोट], [नाम दिया गया], [नाम निक], [वजन], [ ऊंचाई], [चमगादड़], [फेंकता है], [डेब्यू], [फाइनलगेम], [कॉलेज], [लाहमैन 40आईडी], [लाहमान 45आईडी], [रेट्रोआईडी], [होल्त्ज़िड], [बीबीआरएफआईडी] [डीबीओ] से। [खिलाड़ी] जहां [लहमानिड]> 10000;

और अगर हम sys.dm_db_stats_properties की जांच करते हैं, तो हम पंक्ति संशोधन देख सकते हैं:

चुनें [sch]।[नाम] AS [स्कीमा], [तो]। [नाम] AS [ऑब्जेक्टनाम], [तो]। ], [sp]। [last_updated] AS [StatsLastUpdated] , [sp]। [rows] AS [RowsInTable] , [sp]। [sys]। [ऑब्जेक्ट्स] [तो] [sys] में शामिल हों। [आंकड़े] [एसएस] पर [तो]। [ऑब्जेक्ट_आईडी] =[एसएस]। [ऑब्जेक्ट_आईडी] [एसआईएस] में शामिल हों। [स्कीमा] [एसएच] चालू [ so]। [schema_id] =[sch]। [schema_id] बाहरी आवेदन [sys]। [dm_db_stats_properties] ([इसलिए]। [object_id], [ss]। [stats_id]) spWHERE [तो]। [नाम] =' प्लेयरपोस्टसीज़न';

sys.dm_db_stats_properties के माध्यम से अनुक्रमित दृश्य में संशोधित पंक्तियां

और केवल मनोरंजन के लिए, यदि हम sys.sysindexes की जाँच करते हैं, तो हम वहाँ भी संशोधन देख सकते हैं:

चुनें [तो]। .[वस्तुओं] [तो] पर [सी]। [आईडी] =[तो]। [वस्तु_आईडी] जहां [तो]। [नाम] ='प्लेयर पोस्ट सीजन'; 

sys.sysindexes के माध्यम से अनुक्रमित दृश्य में संशोधित पंक्तियां

अब sys.sysindexes को हटा दिया गया है, लेकिन अगर आपको मेरी पिछली पोस्ट याद है, तो यह देखने के लिए कि क्या संशोधित किया गया है, sp_updatestats का उपयोग करता है। लेकिन... sys.indexes के लिए ऑब्जेक्ट सूची sys.objects के विरुद्ध क्वेरी द्वारा संचालित होती है, जो, यदि आपको याद है, तो उपयोगकर्ता तालिकाओं ('U') और आंतरिक तालिकाओं ('IT') पर फ़िल्टर करती है। इसमें उस फ़िल्टर में दृश्य ('V') शामिल नहीं हैं। जैसे, जब हम sp_updatestats चलाते हैं और आउटपुट (संक्षिप्तता के लिए शामिल नहीं) की जांच करते हैं, तो हमारे PlayerPostSeason दृश्य का कोई उल्लेख नहीं होता है।

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

चुनें *से [PlayerPostSeason]जहां [nameFirst] ='Madison';GO

गैर-क्लस्टर किए गए इंडेक्स के लिए SELECT से क्वेरी प्लान

हम योजना में देख सकते हैं कि NCI_PlayerPostSeason_Name गैर-संकुल अनुक्रमणिका का उपयोग किया गया था, और यदि हम आँकड़ों की जाँच करें:

स्वचालित अपडेट के बाद के आंकड़े

निश्चित रूप से, गैर-संकुल सूचकांक के आंकड़े अपडेट कर दिए गए हैं। लेकिन निश्चित रूप से हम आंकड़ों को प्रबंधित करने के लिए ऑटो अपडेट पर भरोसा नहीं करना चाहते हैं, हम सक्रिय रहना चाहते हैं। हमारे पास दो विकल्प हैं:

  • रखरखाव कार्य
  • कस्टम स्क्रिप्ट

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

sqlcmd -E -S $(ESCAPE_SQUOTE(SRVR)) -d मास्टर-Q "निष्पादित [dbo]। [इंडेक्सऑप्टिमाइज़] @ डेटाबेस ='बेसबॉलडेटा', @FragmentationLow =NULL, @FragmentationMedium ='INDEX_REORGANIZE', @FragmentationHigh ='INDEX_REBUILD' ', @ FragmentationLevel1 =5, @FragmentationLevel2 =30, @UpdateStatistics ='ALL', @OnlyModifiedStatistics ='Y', @LogToTable ='Y'" -b

इस विकल्प के साथ, यदि आंकड़े संशोधित किए गए हैं, तो उन्हें अपडेट किया जाएगा, और यदि हम [डीबीओ] की जांच करते हैं। [इंडेक्स ऑप्टिमाइज] संग्रहीत प्रक्रिया हम देख सकते हैं कि ओला संशोधनों के लिए कहां जांचता है:

 -- क्या आँकड़ों में डेटा को अंतिम बार अद्यतन किए जाने के बाद से संशोधित किया गया है? IF @CurrentStatisticsID NULL नहीं है और @UpdateStatistics NULL नहीं है और @OnlyModifiedStatistics ='Y' BEGIN SET @CurrentCommand10 ='' यदि @LockTimeout NULL SET नहीं है @CurrentCommand10 ='SET LOCK_TIMEOUT' + CAST(@LockTimeout * 1000 AS nvar) + '; ' IF (@Version>=10.504000 और @Version <11) या @Version>=11.03000 BEGIN SET @CurrentCommand10 =@CurrentCommand10 + 'USE' + QUOTENAME(@CurrentDatabaseName) + '; अगर मौजूद है (सेलेक्ट * sys.dm_db_stats_properties (@ParamObjectID, @ParamStatisticsID) ​​से जहां संशोधन_काउंटर> 0) शुरू करें @ParamStatisticsModified =1 END' END ELSE BEGIN SET @CurrentCommand10 =@CurrentCommand10 + @CurrentDatabaseName) + '.sys.sysindexes sysindexes जहां sysindexes।[id] =@ParamObjectID और sysindexes।> 

sys.dm_db_stats_properties DMF का समर्थन करने वाले संस्करणों के लिए, Ola इसे संशोधित किए गए किसी भी आँकड़ों के लिए जाँचता है, और उन संस्करणों के लिए जो नए sys.dm_db_stats_properties DMF का समर्थन नहीं करते हैं, sys.sysindexes सिस्टम तालिका की जाँच की जाती है। यहां मेरी एकमात्र शिकायत यह है कि स्क्रिप्ट उसी तरह व्यवहार करती है जैसे sp_updatestats:यदि कम से कम एक पंक्ति को संशोधित किया गया है, तो आंकड़े अपडेट किए जाएंगे।

यदि आप आँकड़ों के प्रबंधन के लिए अपना कोड नहीं लिख रहे हैं, तो मैं ओला की स्क्रिप्ट के साथ रहने की सलाह दूंगा। लेकिन अगर आप अपने अपडेट को थोड़ा और लक्षित करना चाहते हैं, तो मैं sys.dm_db_stats_properties का उपयोग करने की सलाह दूंगा। यह DMF केवल SQL Server 2008R2 SP2 और उच्चतर, और SQL Server 2012 SP1 और उच्चतर के लिए उपलब्ध है, इसलिए यदि आप निम्न संस्करण पर हैं, तो आपको sys.indexes का उपयोग करने की आवश्यकता होगी। लेकिन आप में से जिनके पास sys.dm_db_stats_properties तक पहुंच है, उनके लिए यहां एक प्रश्न है जो आपको आरंभ करने के लिए है:

चुनें [sch]।[नाम] AS [स्कीमा], [तो]। [नाम] AS [ऑब्जेक्टनाम], [तो]। ], [sp]। [last_updated] AS [StatsLastUpdated] , [sp]। [rows] AS [RowsInTable] , [sp]। [एसपी]। [पंक्तियां] दशमलव के रूप में (18, 2)) एएस [प्रतिशत नमूना], [एसपी]। [संशोधन_काउंटर] एएस [पंक्ति संशोधन], कास्ट (100 * [एसपी]। [संशोधन_काउंटर] / [एसपी]। [पंक्तियां ] दशमलव के रूप में(18, 2)) के रूप में [प्रतिशत परिवर्तन] [sys] से। .[object_id]INNER जॉइन [sys]।[स्कीमा] AS [sch] ऑन [सो]। , [एसएस]। [stats_id]) एएस [एसपी] जहां [तो]। [प्रकार] में ('यू', 'वी') और ((कास्ट (100 * [एसपी]। [संशोधन_काउंटर] / [एसपी]। [पंक्तियां] दशमलव के रूप में(18,2))>=10.0)) कास्ट द्वारा आदेश (100 * [एसपी]। [संशोधन_काउंटर] / [एसपी]। [पंक्तियां] दशमलव के रूप में (18, 2)) डीईएससी;> 

ध्यान दें कि sys.objects के साथ हम टेबल और व्यू पर फ़िल्टर करते हैं; आप सिस्टम टेबल को शामिल करने के लिए इसे बदल सकते हैं। फिर आप केवल संशोधित पंक्तियों के प्रतिशत के आधार पर पंक्तियों को पुनः प्राप्त करने के लिए विधेय को संशोधित कर सकते हैं, या शायद संशोधन प्रतिशत और पंक्तियों की संख्या के संयोजन (लाखों या अरबों पंक्तियों वाली तालिकाओं के लिए, वह प्रतिशत छोटी तालिकाओं की तुलना में कम हो सकता है)।

सारांश

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. पायथन में MongoEngine के साथ सूचकांक निर्माण को संभालना

  2. प्रदर्शन आश्चर्य और धारणाएँ :NOCOUNT ON करें

  3. आवेदन में जहां भावों के दोहराव को खत्म करना

  4. निष्पादन योजनाओं में अनुक्रमित दृश्य रखरखाव

  5. डाटाबेस सबसेटिंग - आईआरआई वोरसिटी में कैसे करें