दोस्त या दुश्मन? जब मैं अपने पहले वर्ष में SQL सर्वर का उपयोग कर रहा था तब SQL सर्वर दृश्य गरमागरम बहस का विषय रहे हैं। उन्होंने कहा कि यह खराब था क्योंकि यह धीमा था। लेकिन आज कैसा रहेगा?
क्या आप उसी नाव पर हैं जैसे मैं कई साल पहले था? फिर, SQL दृश्यों के बारे में वास्तविक सौदे को जानने के लिए इस यात्रा में मेरे साथ शामिल हों ताकि आप उन्हें सबसे तेज़ संभव तरीके से लिख सकें।
SQL दृश्य वर्चुअल टेबल हैं। एक दृश्य में रिकॉर्ड इसके अंदर एक क्वेरी का परिणाम है। जब भी दृश्य में उपयोग की जाने वाली आधार तालिकाएँ अद्यतन होती हैं, तो यह दृश्य को भी अद्यतन करती हैं। आप कुछ मामलों में एक तालिका के रूप में रिकॉर्ड को सम्मिलित, अद्यतन और हटा भी सकते हैं। हालांकि मैंने खुद यह कोशिश नहीं की है।
इसी तरह किसी तालिका के लिए, आप एक दृश्य बना सकते हैं, बदल सकते हैं या छोड़ सकते हैं। आप कुछ प्रतिबंधों के साथ एक अनुक्रमणिका भी बना सकते हैं।
ध्यान दें कि मैंने नमूना कोड में SQL Server 2019 का उपयोग किया है।
1. SQL दृश्यों के उचित और अनुचित उपयोग के बारे में जानें
सबसे पहले, मूल बातें।
SQL व्यू किसके लिए हैं?
यह निर्णायक है। यदि आप इसे एक पेचकश के लिए एक हथौड़ा के रूप में उपयोग करते हैं, तो तेजी से SQL दृश्यों के बारे में भूल जाएं। सबसे पहले, आइए उचित उपयोग को याद करें:
- डेटाबेस के बारे में प्रत्येक उपयोगकर्ता की धारणा पर ध्यान केंद्रित करने, सरल बनाने और अनुकूलित करने के लिए।
- उपयोगकर्ताओं को सुरक्षा कारणों से केवल वही जानकारी देखने की अनुमति देने के लिए जो उन्हें देखने की आवश्यकता है।
- आश्रित ऐप्स को न तोड़ने के लिए पुरानी तालिका या पुराने स्कीमा को पश्चगामी संगतता प्रदान करने के लिए। सभी आवश्यक परिवर्तन पूर्ण होने तक यह अस्थायी है।
- विभिन्न सर्वरों से आने वाले डेटा को विभाजित करने के लिए। इसलिए, ऐसा लगता है जैसे वे एक सर्वर या इंस्टेंस से एक टेबल हैं।
SQL सर्वर दृश्यों का उपयोग कैसे न करें?
- किसी अन्य दृश्य में दृश्य का पुन:उपयोग करें जिसे अभी तक पुन:उपयोग किया जाएगा, एक अन्य दृश्य। संक्षेप में, गहराई से नेस्टेड विचार। इस मामले में कोड के पुन:उपयोग में कुछ कमियां हैं।
- कीस्ट्रोक्स पर सहेजें। यह पहले वाले से संबंधित है, जो उंगली के दबाव को कम करता है और कोडिंग को तेज करने लगता है।
विचारों का अनुचित उपयोग, यदि अनुमति दी जाती है, तो आपके द्वारा दृश्य बनाने के वास्तविक कारण को अस्पष्ट कर दिया जाएगा। जैसा कि आप बाद में देखेंगे, वास्तविक लाभ अनुचित उपयोग के कथित लाभों से अधिक हैं।
उदाहरण
आइए Microsoft से एक उदाहरण का निरीक्षण करें। vकर्मचारी AdventureWorks . से देखें . यह रहा कोड:
-- Employee names and basic contact information
CREATE VIEW [HumanResources].[vEmployee]
AS
SELECT
e.[BusinessEntityID]
,p.[Title]
,p.[FirstName]
,p.[MiddleName]
,p.[LastName]
,p.[Suffix]
,e.[JobTitle]
,pp.[PhoneNumber]
,pnt.[Name] AS [PhoneNumberType]
,ea.[EmailAddress]
,p.[EmailPromotion]
,a.[AddressLine1]
,a.[AddressLine2]
,a.[City]
,sp.[Name] AS [StateProvinceName]
,a.[PostalCode]
,cr.[Name] AS [CountryRegionName]
,p.[AdditionalContactInfo]
FROM [HumanResources].[Employee] e
INNER JOIN [Person].[Person] p
ON p.[BusinessEntityID] = e.[BusinessEntityID]
INNER JOIN [Person].[BusinessEntityAddress] bea
ON bea.[BusinessEntityID] = e.[BusinessEntityID]
INNER JOIN [Person].[Address] a
ON a.[AddressID] = bea.[AddressID]
INNER JOIN [Person].[StateProvince] sp
ON sp.[StateProvinceID] = a.[StateProvinceID]
INNER JOIN [Person].[CountryRegion] cr
ON cr.[CountryRegionCode] = sp.[CountryRegionCode]
LEFT OUTER JOIN [Person].[PersonPhone] pp
ON pp.BusinessEntityID = p.[BusinessEntityID]
LEFT OUTER JOIN [Person].[PhoneNumberType] pnt
ON pp.[PhoneNumberTypeID] = pnt.[PhoneNumberTypeID]
LEFT OUTER JOIN [Person].[EmailAddress] ea
ON p.[BusinessEntityID] = ea.[BusinessEntityID];
GO
इस दृष्टिकोण का उद्देश्य कर्मचारी की बुनियादी जानकारी पर केंद्रित है। यदि मानव संसाधन कर्मचारियों को आवश्यकता हो, तो इसे वेब पेज पर प्रदर्शित किया जा सकता है। क्या इसे अन्य दृश्यों में पुन:उपयोग किया गया था?
इसे आजमाएं:
- SQL सर्वर प्रबंधन स्टूडियो में , AdventureWorks . की तलाश करें डेटाबेस।
- दृश्य फ़ोल्डर का विस्तार करें और देखें [HumanResources].[vEmployee].
- इस पर राइट-क्लिक करें और निर्भरता देखें select चुनें ।
यदि आप इस दृश्य के आधार पर एक और दृश्य देखते हैं, जो तब एक अलग दृश्य पर निर्भर करता है, तो Microsoft ने हमें एक बुरा उदाहरण दिया। लेकिन फिर, कोई अन्य दृश्य निर्भरताएँ नहीं हैं।
आइए अगले पर चलते हैं।
2. SQL दृश्यों पर मिथक को दूर करें
जब SQL सर्वर दृश्य से चयन करें . को संसाधित करता है , यह WHERE क्लॉज या बाहरी क्वेरी में शामिल होने से पहले कोड का मूल्यांकन करता है। अधिक तालिकाओं के जुड़ने से, यह आधार तालिकाओं से चयन करें . की तुलना में धीमा होगा एक ही परिणाम के साथ।
कम से कम, मुझे यही बताया गया था जब मैंने SQL का उपयोग करना शुरू किया था। यह मिथक है या नहीं, इसका पता लगाने का एक ही तरीका है। आइए एक व्यावहारिक उदाहरण की ओर मुड़ें।
SQL व्यू कैसे काम करता है
Microsoft ने हमें अंतहीन बहस के लिए अंधेरे में नहीं छोड़ा। हमारे पास यह देखने के लिए टूल हैं कि क्वेरी कैसे काम करती हैं, जैसे सांख्यिकी IO और वास्तविक निष्पादन योजना . हम अपने सभी उदाहरणों में इनका उपयोग करेंगे। आइए पहले लेते हैं।
USE AdventureWorks
GO
SELECT * FROM HumanResources.vEmployee e
WHERE e.BusinessEntityID = 105
यह देखने के लिए कि SQL सर्वर दृश्य को संसाधित करते समय क्या हो रहा है, आइए वास्तविक निष्पादन योजना का निरीक्षण करें चित्र 1 में। हम इसकी तुलना vकर्मचारी . के लिए क्रिएट व्यू कोड से करते हैं पिछले अनुभाग में।
जैसा कि आप देख सकते हैं, SQL सर्वर द्वारा संसाधित पहले नोड INNER JOIN का उपयोग करने वाले हैं। फिर, यह LEFT OUTER JOINs को प्रोसेस करने के लिए आगे बढ़ता है।
चूंकि हम WHERE क्लॉज के लिए कहीं भी फ़िल्टर नोड नहीं देख सकते हैं, यह उन नोड्स में से एक में होना चाहिए। यदि आप सभी नोड्स के गुणों का निरीक्षण करते हैं, तो आप कर्मचारी तालिका में संसाधित WHERE क्लॉज देखेंगे। मैंने इसे चित्र 1 में एक बॉक्स में संलग्न किया है। यह साबित करने के लिए कि यह वहां है, उस नोड के गुणों के लिए चित्र 2 देखें:
विश्लेषण
तो, vकर्मचारी . में SELECT स्टेटमेंट था WHERE क्लॉज लागू होने से पहले व्यू का मूल्यांकन या प्रोसेस किया गया था? निष्पादन योजना से पता चलता है कि यह नहीं था। अगर ऐसा होता, तो यह SELECT नोड के सबसे करीब दिखना चाहिए।
मुझे जो बताया गया वह एक मिथक था। SQL व्यू के उचित उपयोग की गलतफहमी के कारण मैं कुछ अच्छा करने से बच रहा था।
अब जबकि हम जानते हैं कि SQL सर्वर किसी दृश्य से SELECT को कैसे संसाधित करता है , प्रश्न बना रहता है:क्या यह किसी दृश्य का उपयोग न करने की तुलना में धीमा है?
व्यू से चुनें बनाम बेस टेबल से चुनें - कौन सा तेज़ चलेगा?
सबसे पहले, हमें vEmployee . के अंदर SELECT स्टेटमेंट को एक्सट्रैक्ट करना होगा दृश्य का उपयोग करते समय हमारे पास वही परिणाम देखें और उत्पन्न करें। नीचे दिया गया कोड वही WHERE क्लॉज दिखाता है:
USE AdventureWorks
GO
-- SELECT FROM a view
SELECT * FROM HumanResources.vEmployee e
WHERE e.BusinessEntityID = 105
-- SELECT FROM Base Tables
SELECT
e.[BusinessEntityID]
,p.[Title]
,p.[FirstName]
,p.[MiddleName]
,p.[LastName]
,p.[Suffix]
,e.[JobTitle]
,pp.[PhoneNumber]
,pnt.[Name] AS [PhoneNumberType]
,ea.[EmailAddress]
,p.[EmailPromotion]
,a.[AddressLine1]
,a.[AddressLine2]
,a.[City]
,sp.[Name] AS [StateProvinceName]
,a.[PostalCode]
,cr.[Name] AS [CountryRegionName]
,p.[AdditionalContactInfo]
FROM [HumanResources].[Employee] e
INNER JOIN [Person].[Person] p
ON p.[BusinessEntityID] = e.[BusinessEntityID]
INNER JOIN [Person].[BusinessEntityAddress] bea
ON bea.[BusinessEntityID] = e.[BusinessEntityID]
INNER JOIN [Person].[Address] a
ON a.[AddressID] = bea.[AddressID]
INNER JOIN [Person].[StateProvince] sp
ON sp.[StateProvinceID] = a.[StateProvinceID]
INNER JOIN [Person].[CountryRegion] cr
ON cr.[CountryRegionCode] = sp.[CountryRegionCode]
LEFT OUTER JOIN [Person].[PersonPhone] pp
ON pp.BusinessEntityID = p.[BusinessEntityID]
LEFT OUTER JOIN [Person].[PhoneNumberType] pnt
ON pp.[PhoneNumberTypeID] = pnt.[PhoneNumberTypeID]
LEFT OUTER JOIN [Person].[EmailAddress] ea
ON p.[BusinessEntityID] = ea.[BusinessEntityID]
WHERE e.BusinessEntityID = 105
फिर, हम सांख्यिकी IO का निरीक्षण करते हैं और एक शोप्लान की तुलना करें . करते हैं . बेस टेबल से क्वेरी करने की तुलना में एक दृश्य से एक क्वेरी को कितने संसाधनों की आवश्यकता होगी? चित्र 3 देखें।
यहां, किसी व्यू या बेस टेबल से पूछताछ करने पर वही लॉजिकल रीड का उपभोग होगा। दोनों ने 19*8KB पेज का इस्तेमाल किया। इसके आधार पर, यह एक टाई है कि कौन तेज है। दूसरे शब्दों में, किसी दृश्य का उपयोग करने से प्रदर्शन प्रभावित नहीं होगा। आइए वास्तविक निष्पादन योजना की तुलना करें दोनों का शोप्लान की तुलना करें . का उपयोग करके :
क्या आपको आरेख का छायांकित भाग दिखाई देता है? QueryPlanHash . के बारे में कैसा रहेगा दोनों? चूंकि दोनों प्रश्नों के समान QueryPlanHash . हैं और समान संचालन, या तो देखें या आधार तालिकाएँ SQL सर्वर द्वारा समान संसाधित की जाएंगी ।
वही लॉजिकल रीड और सैंपल की एक ही योजना हमें बताती है कि दोनों एक ही प्रदर्शन करेंगे। इस प्रकार, उच्च तार्किक पठन होने से आपकी क्वेरी धीमी हो जाएगी चाहे आप विचारों का उपयोग करें या नहीं। इस तथ्य को जानने से आपको समस्या को ठीक करने में मदद मिलेगी और आपके विचार तेज़ी से चलेंगे।
दुर्भाग्य से, कुछ बुरी खबर है।
SQL दृश्यों को तालिका में शामिल करना
आपने पहले जो देखा वह एक दृश्य से एक चयन है जिसमें कोई शामिल नहीं है। हालांकि, क्या होगा यदि आप किसी तालिका को किसी दृश्य से जोड़ते हैं?
आइए एक और उदाहरण की समीक्षा करें। इस बार, हम vSalesPerson . का उपयोग करते हैं AdventureWorks . में देखें - संपर्क जानकारी और बिक्री कोटा के साथ एक विक्रेता सूची। फिर से, हम स्टेटमेंट की तुलना बेस टेबल से SELECT से करते हैं:
-- get the total sales orders for each salesperson
-- using the view joined with SalesOrderHeader
SELECT
sp.FirstName
,sp.MiddleName
,sp.LastName
,SUM(soh.TotalDue) AS TotalSalesOrders
FROM Sales.vSalesPerson sp
INNER JOIN Sales.SalesOrderHeader soh ON sp.BusinessEntityID = soh.SalesPersonID
GROUP BY sp.LastName, sp.MiddleName, sp.FirstName
-- using base tables
SELECT
p.FirstName
,p.MiddleName
,p.LastName
,SUM(soh.TotalDue) AS TotalSalesOrders
FROM sales.SalesPerson sp
INNER JOIN Person.Person p ON sp.BusinessEntityID = P.BusinessEntityID
INNER JOIN Sales.SalesOrderHeader soh ON sp.BusinessEntityID = soh.SalesPersonID
GROUP BY p.LastName, p.MiddleName, p.FirstName
अगर आपको लगता है कि यह भी ऐसा ही होगा, तो आँकड़ों की जाँच करें:
हैरान? vSalesPerson . में शामिल होना SalesOrderHeader . के साथ देखें केवल बेस टेबल (774 x 8KB) का उपयोग करने की तुलना में तालिका को जबरदस्त संसाधनों (28,240 x 8KB) की आवश्यकता होती है। यह भी ध्यान दें कि इसमें कुछ टेबल शामिल हैं जिनकी हमें आवश्यकता नहीं थी (लाल बक्से के भीतर टेबल)। SalesOrderHeader . पर उच्च तार्किक पढ़ने की तो बात ही छोड़िए दृश्य का उपयोग करते समय।
लेकिन बात यहीं खत्म नहीं होती।
वास्तविक निष्पादन योजना अधिक प्रकट करती है
आधार तालिकाओं के लिए क्वेरी की वास्तविक निष्पादन योजना पर ध्यान दें:
चित्रण एक बहुत ही सामान्य निष्पादन योजना दिखाता है। लेकिन दृश्य के साथ देखें:
चित्र 7 में निष्पादन योजना चित्र 5 में सांख्यिकी IO के साथ मेल खाती है। हम उन तालिकाओं को देख सकते हैं जिनकी हमें आवश्यकता नहीं है। एक कुंजी लुकअप . भी है एक पंक्ति अनुमान के साथ नोड जो वास्तविक पंक्तियों की तुलना में एक हजार से अधिक रिकॉर्ड बंद है। अंत में, SELECT नोड में एक चेतावनी भी दिखाई देती है। यह क्या हो सकता है?
वह क्या है अत्यधिक अनुदान SELECT नोड में चेतावनी?
एक अत्यधिक अनुदान तब होता है जब अधिकतम उपयोग की गई स्मृति दी गई स्मृति की तुलना में बहुत छोटी होती है। इस मामले में, 1024KB प्रदान किया गया था, लेकिन केवल 16KB का उपयोग किया गया था।
मेमोरी ग्रांट योजना को चलाने के लिए आवश्यक KB में मेमोरी की अनुमानित मात्रा है।
यह कुंजी लुकअप . में गलत अनुमान हो सकता है नोड और / या उन तालिकाओं को शामिल करना जिनकी हमें उस योजना में आवश्यकता नहीं थी जिसके कारण यह हुआ। साथ ही, बहुत अधिक दी गई स्मृति अवरोधन का कारण बन सकती है। शेष 1008KB अन्य कार्यों के लिए उपयोगी हो सकता था।
आखिरकार, जब आप किसी तालिका के साथ दृश्य में शामिल हुए तो कुछ गलत हो गया। अगर हम बेस टेबल से पूछताछ करते हैं तो हमें इन समस्याओं का सामना नहीं करना पड़ेगा।
टेकअवे
यह एक लंबी व्याख्या थी। हालांकि, हम जानते हैं कि WHERE क्लॉज या बाहरी क्वेरी में शामिल होने से पहले दृश्यों का मूल्यांकन या संसाधित नहीं किया जाता है। हमने यह भी साबित कर दिया कि दोनों एक ही प्रदर्शन करेंगे।
दूसरी ओर, जब हम किसी दृश्य को किसी तालिका से जोड़ते हैं तो एक मामला होता है। यह उन तालिकाओं के जोड़ का उपयोग करता है जिनकी हमें आवश्यकता नहीं है। जब तक हम सांख्यिकी IO और वास्तविक निष्पादन योजना की जाँच नहीं करते, वे हमारे लिए अदृश्य हैं। यह सब प्रदर्शन को नुकसान पहुंचा सकता है, और समस्याएं कहीं से भी आ सकती हैं।
इसलिए:
- हमें पता होना चाहिए कि विचारों सहित क्वेरी अंदर से कैसे काम करती हैं।
- सांख्यिकी आईओ और वास्तविक निष्पादन योजनाएं प्रकट करेंगी कि प्रश्न और विचार कैसे काम करेंगे।
- हम किसी दृश्य को केवल तालिका में शामिल नहीं कर सकते और लापरवाही से उसका पुन:उपयोग नहीं कर सकते। हमेशा सांख्यिकी IO और वास्तविक निष्पादन योजनाओं की जाँच करें! दृश्यों का पुन:उपयोग करने और उन्हें "बेहतर" कोडिंग उत्पादकता के लिए नेस्ट करने के बजाय, मैं एक IntelliSense और कोड पूर्णता टूल जैसे SQL पूर्ण का उपयोग करता हूं।
तब हम यह सुनिश्चित कर सकते हैं कि हम ऐसे विचार न लिखें जिनके सही परिणाम हों लेकिन घोंघे की तरह चलें।
3. अनुक्रमित दृश्यों का प्रयास करें
अनुक्रमित विचार वही हैं जो नाम का तात्पर्य है। यह सेलेक्ट स्टेटमेंट को परफॉर्मेंस बूस्ट दे सकता है। लेकिन टेबल इंडेक्स की तरह, बेस टेबल बड़े और लगातार अपडेट होने पर यह प्रदर्शन को प्रभावित कर सकता है।
यह देखने के लिए कि कैसे अनुक्रमित दृश्य क्वेरी प्रदर्शन को बेहतर बना सकते हैं, आइए vStateProvinceCountryRegion की जांच करें। AdventureWorks . में देखें . दृश्य StateProvinceID . पर अनुक्रमित है और देशक्षेत्र कोड . यह एक संकुल, अद्वितीय अनुक्रमणिका है।
आइए इंडेक्स न होने और इंडेक्स होने के दृश्य के Statistics IO की तुलना करें। इससे हम सीखते हैं कि हमारा SQL सर्वर कितने 8KB पेज पढ़ेगा:
चित्र दिखाता है कि vStateProvinceCountryRegion . में एक अनुक्रमणिका है दृश्य तार्किक पठन को आधा कर देता है। सूचकांक न होने की तुलना में यह 50% सुधार है।
यह सुनकर अच्छा लगा।
फिर भी, लापरवाही से अपने विचारों में अनुक्रमणिका न जोड़ें। सख्त नियमों की एक लंबी सूची होने के अलावा, 1 अद्वितीय, क्लस्टर इंडेक्स होने के अलावा, यह प्रदर्शन को नुकसान पहुंचा सकता है, जैसे कि इंडेक्स को टेबल में जोड़ना। साथ ही, अगर इंडेक्स जोड़ने के बाद तार्किक पठन में कमी आती है, तो आँकड़ों की जाँच करें।
टेकअवे
जैसा कि हमने अपने उदाहरण में देखा है, अनुक्रमित दृश्य SQL दृश्य प्रदर्शन में सुधार कर सकते हैं।
बोनस युक्ति
किसी भी अन्य क्वेरी की तरह, SQL दृश्य तेजी से चलेंगे यदि:
- आंकड़े अपडेट किए गए हैं
- गुम इंडेक्स जोड़े जाते हैं
- इंडेक्स को डीफ़्रैग्मेन्ट किया जाता है
- इंडेक्स ने सही FILLFACTOR का उपयोग किया
निष्कर्ष
SQL व्यूज अच्छे हैं या बुरे?
SQL दृश्य अच्छे हैं यदि हम उन्हें सही ढंग से लिखते हैं और यह देखने के लिए जांचते हैं कि उन्हें कैसे संसाधित किया जाएगा। हमारे पास सांख्यिकी IO और वास्तविक निष्पादन योजना जैसे उपकरण हैं - उनका उपयोग करें! अनुक्रमित दृश्य भी प्रदर्शन में सुधार कर सकते हैं।
इस डाक की तरह? कृपया अपने पसंदीदा सोशल मीडिया प्लेटफॉर्म पर कुछ प्यार साझा करें।