पैरामीटर डेटा प्रकार
जैसा कि इस श्रृंखला के पहले भाग में उल्लेख किया गया है, स्पष्ट रूप से पैरामीटर करने के लिए बेहतर कारणों में से एक यह है कि आपका पैरामीटर डेटा प्रकारों पर पूर्ण नियंत्रण है। इस क्षेत्र में सरल पैरामीटरकरण में कई विचित्रताएं हैं, जिसके परिणामस्वरूप अधिक पैरामीटरयुक्त योजनाओं को अपेक्षा से अधिक कैश किया जा सकता है, या गैर-पैरामीटरीकृत संस्करण की तुलना में अलग-अलग परिणाम मिल सकते हैं।
जब SQL सर्वर सरल पैरामीटरकरण लागू करता है एक तदर्थ विवरण के लिए, यह प्रतिस्थापन पैरामीटर के डेटा प्रकार के बारे में अनुमान लगाता है। मैं श्रृंखला में बाद में अनुमान लगाने के कारणों को कवर करूंगा।
कुछ समय के लिए, आइए SQL सर्वर 2019 CU 14 पर स्टैक ओवरफ़्लो 2010 डेटाबेस का उपयोग करते हुए कुछ उदाहरण देखें। डेटाबेस संगतता 150 पर सेट है, और समानता के लिए लागत सीमा अभी के लिए समानांतरवाद से बचने के लिए 50 पर सेट है:
ALTER DATABASE SCOPED CONFIGURATION
CLEAR PROCEDURE_CACHE;
GO
SELECT U.DisplayName
FROM dbo.Users AS U
WHERE U.Reputation = 252;
GO
SELECT U.DisplayName
FROM dbo.Users AS U
WHERE U.Reputation = 25221;
GO
SELECT U.DisplayName
FROM dbo.Users AS U
WHERE U.Reputation = 252552; इन बयानों के परिणामस्वरूप छह कैश्ड योजनाएं होती हैं, तीन तदर्थ और तीन तैयार :
विभिन्न प्रकार के अनुमान
तैयार . में विभिन्न पैरामीटर डेटा प्रकारों पर ध्यान दें योजनाएं।
डेटा प्रकार अनुमान
प्रत्येक डेटा प्रकार का अनुमान कैसे लगाया जाता है, इसका विवरण जटिल और अपूर्ण रूप से प्रलेखित है। एक प्रारंभिक बिंदु के रूप में, SQL सर्वर मूल्य के पाठ्य प्रस्तुतिकरण से एक मूल प्रकार का अनुमान लगाता है, फिर सबसे छोटे संगत उपप्रकार का उपयोग करता है।
उद्धरण चिह्नों या दशमलव बिंदु के बिना संख्याओं की एक स्ट्रिंग के लिए, SQL सर्वर tinyint . से चुनता है , smallint , और integer . integer . की सीमा से बाहर की ऐसी संख्याओं के लिए , SQL सर्वर numeric का उपयोग करता है सबसे छोटी संभव सटीकता के साथ। उदाहरण के लिए, संख्या 2,147,483,648 को numeric(10,0) के रूप में टाइप किया जाता है . bigint प्रकार सर्वर-साइड पैरामीटरकरण के लिए उपयोग नहीं किया जाता है। यह पैराग्राफ पिछले उदाहरणों में चयनित डेटा प्रकारों की व्याख्या करता है।
संख्याओं के तार के साथ दशमलव बिंदु की व्याख्या numeric . के रूप में की जाती है , एक सटीक और पैमाने के साथ जो प्रदान किए गए मान को समाहित करने के लिए पर्याप्त है। मुद्रा के प्रतीक के साथ लगे स्ट्रिंग्स की व्याख्या money . के रूप में की जाती है . वैज्ञानिक संकेतन में स्ट्रिंग्स का अनुवाद float . में होता है . smallmoney और real प्रकार नियोजित नहीं हैं।
datetime और uniqueidentifer प्राकृतिक स्ट्रिंग प्रारूपों से प्रकारों का अनुमान नहीं लगाया जा सकता है। datetime प्राप्त करने के लिए या uniqueidentifer पैरामीटर प्रकार, शाब्दिक मान ODBC एस्केप प्रारूप में प्रदान किया जाना चाहिए। उदाहरण के लिए {d '1901-01-01'} , {ts '1900-01-01 12:34:56.790'} , या {guid 'F85C72AB-15F7-49E9-A949-273C55A6C393'} . अन्यथा, इच्छित तिथि या UUID शाब्दिक एक स्ट्रिंग के रूप में टाइप किया गया है। datetime . के अलावा अन्य दिनांक और समय प्रकार उपयोग नहीं किया जाता है।
सामान्य स्ट्रिंग और बाइनरी अक्षर varchar(8000) . के रूप में टाइप किए जाते हैं , nvarchar(4000) , या varbinary(8000) उपयुक्त के रूप में, जब तक कि शाब्दिक 8000 बाइट्स से अधिक न हो, जिस स्थिति में max भिन्न का प्रयोग किया जाता है। यह योजना कैश प्रदूषण और विशिष्ट लंबाई के उपयोग के परिणामस्वरूप होने वाले पुन:उपयोग के निम्न स्तर से बचने में मदद करती है।
CAST का उपयोग करना संभव नहीं है या CONVERT पैरामीटर के लिए डेटा प्रकार सेट करने के कारणों के लिए मैं इस श्रृंखला में बाद में विस्तार से बताऊंगा। इसका एक उदाहरण अगले भाग में है।
मैं मजबूर पैरामीटरकरण को कवर नहीं करूंगा इस श्रृंखला में, लेकिन मैं डेटा प्रकार अनुमान के नियमों का उल्लेख करना चाहता हूं, उस मामले में सरल पैरामीटरकरण की तुलना में कुछ महत्वपूर्ण अंतर हैं . SQL Server 2005 तक जबरन पैरामीटरकरण नहीं जोड़ा गया था, इसलिए Microsoft के पास सरल पैरामीटराइज़ेशन से कुछ सबक शामिल करने का अवसर था। अनुभव, और पिछड़े-संगतता मुद्दों के बारे में ज्यादा चिंता करने की ज़रूरत नहीं थी।
संख्यात्मक प्रकार
दशमलव बिंदु वाली संख्याओं और integer . की सीमा से परे पूर्ण संख्याओं के लिए , अनुमानित प्रकार के नियम योजना के पुन:उपयोग और कैश प्रदूषण के लिए विशेष समस्याएं प्रस्तुत करते हैं।
दशमलव का प्रयोग करते हुए निम्नलिखित प्रश्न पर विचार करें:
ALTER DATABASE SCOPED CONFIGURATION
CLEAR PROCEDURE_CACHE;
GO
DROP TABLE IF EXISTS dbo.Test;
GO
CREATE TABLE dbo.Test
(
SomeValue decimal(19,8) NOT NULL
);
GO
SELECT
T.SomeValue
FROM dbo.Test AS T
WHERE
T.SomeValue >= 987.65432
AND T.SomeValue < 123456.789;
यह क्वेरी सरल मानकीकरण . के लिए योग्य है . SQL सर्वर आपूर्ति किए गए मानों को शामिल करने में सक्षम पैरामीटर के लिए सबसे छोटी परिशुद्धता और स्केल चुनता है। इसका मतलब है कि यह numeric(8,5) . को चुनता है 987.65432 . के लिए और numeric(9,3) 123456.789 . के लिए :
अनुमानित संख्यात्मक डेटा प्रकार
ये अनुमानित प्रकार decimal(19,8) से मेल नहीं खाते कॉलम का प्रकार, इसलिए निष्पादन योजना में पैरामीटर के चारों ओर एक रूपांतरण दिखाई देता है:
स्तंभ प्रकार में रूपांतरण
ये रूपांतरण इस विशेष मामले में केवल एक छोटी रनटाइम अक्षमता का प्रतिनिधित्व करते हैं। अन्य स्थितियों में, कॉलम डेटा प्रकार और अनुमानित प्रकार के पैरामीटर के बीच एक बेमेल इंडेक्स की तलाश को रोक सकता है या गतिशील खोज के निर्माण के लिए SQL सर्वर को अतिरिक्त कार्य करने की आवश्यकता हो सकती है।
यहां तक कि जहां परिणामी निष्पादन योजना उचित लगती है, कार्डिनैलिटी अनुमान पर प्रकार बेमेल के प्रभाव के कारण एक प्रकार का बेमेल आसानी से योजना की गुणवत्ता को प्रभावित कर सकता है। मिलान करने वाले डेटा प्रकारों का उपयोग करना और भावों से उत्पन्न होने वाले व्युत्पन्न प्रकारों पर सावधानीपूर्वक ध्यान देना हमेशा सर्वोत्तम होता है।
पुन:उपयोग की योजना बनाएं
वर्तमान योजना के साथ मुख्य मुद्दा विशिष्ट अनुमानित प्रकार है जो कैश्ड योजना मिलान को प्रभावित करता है और इसलिए पुन:उपयोग करता है। आइए समान सामान्य रूप की कुछ और क्वेरीज़ चलाते हैं:
SELECT
T.SomeValue
FROM dbo.Test AS T
WHERE
T.SomeValue >= 98.76
AND T.SomeValue < 123.4567;
GO
SELECT
T.SomeValue
FROM dbo.Test AS T
WHERE
T.SomeValue >= 1.2
AND T.SomeValue < 1234.56789;
GO अब प्लान कैश को देखें:
SELECT
CP.usecounts,
CP.objtype,
ST.[text]
FROM sys.dm_exec_cached_plans AS CP
CROSS APPLY sys.dm_exec_sql_text (CP.plan_handle) AS ST
WHERE
ST.[text] NOT LIKE '%dm_exec_cached_plans%'
AND ST.[text] LIKE '%SomeValue%Test%'
ORDER BY
CP.objtype ASC; यह एक तदर्थ . दिखाता है और तैयार हमारे द्वारा सबमिट की गई प्रत्येक क्वेरी के लिए विवरण:
तैयार किए गए बयानों को अलग करें
पैरामीटरयुक्त टेक्स्ट समान है, लेकिन पैरामीटर डेटा प्रकार भिन्न हैं, इसलिए अलग-अलग योजनाएं कैश की जाती हैं, और कोई योजना पुन:उपयोग नहीं होती है।
यदि हम पैमाने या सटीकता के विभिन्न संयोजनों के साथ प्रश्न सबमिट करना जारी रखते हैं, तो एक नया तैयार योजना बनाई जाएगी और हर बार कैश की जाएगी। याद रखें कि प्रत्येक पैरामीटर का अनुमानित प्रकार कॉलम डेटा प्रकार द्वारा सीमित नहीं है, इसलिए हम जमा किए गए संख्यात्मक शाब्दिकों के आधार पर कैश्ड योजनाओं की एक जबरदस्त संख्या के साथ समाप्त हो सकते हैं। numeric(1,0) . से संयोजनों की संख्या से numeric(38,38) कई पैरामीटर के बारे में सोचने से पहले ही बड़ा है।
स्पष्ट पैरामीटरकरण
यह समस्या तब उत्पन्न नहीं होती जब हम स्पष्ट पैरामीटरकरण का उपयोग करते हैं, आदर्श रूप से उसी डेटा प्रकार को चुनना जिस कॉलम के साथ पैरामीटर की तुलना की जाती है:
ALTER DATABASE SCOPED CONFIGURATION
CLEAR PROCEDURE_CACHE;
GO
DECLARE
@stmt nvarchar(4000) =
N'SELECT T.SomeValue FROM dbo.Test AS T WHERE T.SomeValue >= @P1 AND T.SomeValue < @P2;',
@params nvarchar(4000) =
N'@P1 numeric(19,8), @P2 numeric(19,8)';
EXECUTE sys.sp_executesql
@stmt,
@params,
@P1 = 987.65432,
@P2 = 123456.789;
EXECUTE sys.sp_executesql
@stmt,
@params,
@P1 = 98.76,
@P2 = 123.4567;
EXECUTE sys.sp_executesql
@stmt,
@params,
@P1 = 1.2,
@P2 = 1234.56789; स्पष्ट मानदंड के साथ, प्लान कैश क्वेरी केवल एक योजना कैश्ड दिखाती है, तीन बार उपयोग की जाती है, और किसी प्रकार के रूपांतरण की आवश्यकता नहीं होती है:
स्पष्ट पैरामीटरीकरण
अंतिम साइड नोट के रूप में, मैंने decimal . का उपयोग किया है और numeric इस खंड में परस्पर। वे तकनीकी रूप से . हैं विभिन्न प्रकार, हालांकि समानार्थी होने और समान व्यवहार करने के लिए प्रलेखित। आमतौर पर ऐसा होता है, लेकिन हमेशा नहीं:
-- Raises error 8120: -- Column 'dbo.Test.SomeValue' is invalid in the select list -- because it is not contained in either an aggregate function -- or the GROUP BY clause. SELECT CONVERT(decimal(19,8), T.SomeValue) FROM dbo.Test AS T GROUP BY CONVERT(numeric(19,8), T.SomeValue);
यह शायद एक छोटा पार्सर बग है, लेकिन यह अभी भी सुसंगत होने के लिए भुगतान करता है (जब तक कि आप एक लेख नहीं लिख रहे हैं और एक दिलचस्प अपवाद को इंगित करना चाहते हैं)।
अंकगणित संचालिका
दस्तावेज़ीकरण में दिए गए एक उदाहरण के आधार पर एक और किनारे का मामला है जिसे मैं संबोधित करना चाहता हूं, लेकिन थोड़ा और विस्तार से (और शायद सटीकता):
-- The dbo.LinkTypes table contains two rows -- Uses simple parameterization SELECT r = CONVERT(float, 1./ 7) FROM dbo.LinkTypes AS LT; -- No simple parameterization due to -- constant-constant comparison SELECT r = CONVERT(float, 1./ 7) FROM dbo.LinkTypes AS LT WHERE 1 = 1;
दस्तावेज के अनुसार परिणाम भिन्न हैं:
विभिन्न परिणाम
सरल Parameterization के साथ
जब सरल मानकीकरण होता है, SQL सर्वर दोनों शाब्दिक मानों को पैरामीटर करता है। 1. मान numeric(1,0) . के रूप में टाइप किया गया है जैसा सोचा था। कुछ असंगत रूप से, 7 integer . के रूप में टाइप किया गया है (नहीं tinyint ) समय के साथ, विभिन्न टीमों द्वारा प्रकार के अनुमान के नियम बनाए गए हैं। लीगेसी कोड को तोड़ने से बचने के लिए व्यवहार बनाए रखा जाता है।
अगले चरण में / . शामिल है अंकगणितीय ऑपरेटर। विभाजन करने से पहले SQL सर्वर को संगत प्रकारों की आवश्यकता होती है। दिया गया numeric (decimal ) में integer . की तुलना में उच्च डेटा प्रकार की प्राथमिकता है , integer numeric . में बदल दिया जाएगा ।
SQL सर्वर को integer को परोक्ष रूप से रूपांतरित करने की आवश्यकता है करने के लिए numeric . लेकिन किस सटीकता और पैमाने का उपयोग करना है? उत्तर मूल शाब्दिक पर आधारित हो सकता है, जैसा कि SQL सर्वर अन्य परिस्थितियों में करता है, लेकिन यह हमेशा numeric(10) का उपयोग करता है यहाँ।
numeric(1,0) . को विभाजित करने के परिणाम का डेटा प्रकार numeric(10,0) . द्वारा दूसरे . द्वारा निर्धारित किया जाता है नियमों का सेट, सटीकता, पैमाने और लंबाई के लिए दस्तावेज़ीकरण में दिया गया है। परिणाम सटीकता और वहां दिए गए पैमाने के लिए संख्याओं को सूत्रों में प्लग करना, हमारे पास है:
- परिणाम सटीक:
- p1 - s1 + s2 + अधिकतम (6, s1 + p2 + 1)
- =1 - 0 + 0 + अधिकतम (6, 0 + 10 + 1)
- =1 + अधिकतम(6, 11)
- =1 + 11
- =12
- परिणाम पैमाने:
- अधिकतम(6, s1 + p2 + 1)
- =अधिकतम(6, 0 + 10 + 1)
- =अधिकतम(6, 11)
- =11
डेटा प्रकार 1. / 7 इसलिए, numeric(12, 11) . है . यह मान तब float . में बदल जाता है जैसा अनुरोध किया गया है और 0.14285714285 . के रूप में प्रदर्शित किया गया है (दशमलव बिंदु के बाद 11 अंकों के साथ)।
बिना साधारण पैरामीटराइज़ेशन के
जब सरल मानकीकरण नहीं किया जाता है, तो 1. शाब्दिक को numeric(1,0) . के रूप में टाइप किया जाता है पहले जैसा। 7 प्रारंभ में integer के रूप में टाइप किया जाता है भी जैसा कि पहले देखा गया था। मुख्य अंतर है integer numeric(1,0) . में कनवर्ट किया जाता है , इसलिए डिवीजन ऑपरेटर के पास काम करने के लिए सामान्य प्रकार हैं। यह 7 . मान को समाहित करने में सक्षम सबसे छोटी सटीकता और पैमाना है . उपयोग किए गए सरल मानकीकरण याद रखें numeric(10,0) यहाँ।
numeric(1,0) . को विभाजित करने के लिए सटीक और स्केल सूत्र numeric(1,0) . द्वारा एक परिणाम डेटा प्रकार दें numeric(7,6) :
- परिणाम सटीक:
- p1 - s1 + s2 + अधिकतम (6, s1 + p2 + 1)
- =1 - 0 + 0 + अधिकतम (6, 0 + 1 + 1)
- =1 + अधिकतम(6, 2)
- =1 + 6
- =7
- परिणाम पैमाने:
- अधिकतम(6, s1 + p2 + 1)
- =अधिकतम(6, 0 + 1 + 1)
- =अधिकतम(6, 2)
- =6
अंतिम रूपांतरण के बाद float , प्रदर्शित परिणाम 0.142857 . है (दशमलव बिंदु के बाद छह अंकों के साथ)।
इसलिए परिणामों में देखा गया अंतर अंतरिम प्रकार की व्युत्पत्ति के कारण है (numeric(12,11) बनाम numeric(7,6) ) float . में अंतिम रूपांतरण के बजाय ।
यदि आपको float . में रूपांतरण के लिए और सबूत चाहिए तो जिम्मेदार नहीं है, विचार करें:
-- Simple parameterization SELECT r = CONVERT(decimal(13,12), 1. / 7) FROM dbo.LinkTypes AS LT; -- No simple parameterization SELECT r = CONVERT(decimal(13,12), 1. / 7) FROM dbo.LinkTypes AS LT OPTION (MAXDOP 1);
दशमलव के साथ परिणाम
परिणाम पहले की तरह मूल्य और पैमाने में भिन्न होते हैं।
इस अनुभाग में सरल पैरामीटरकरण . के साथ डेटा प्रकार के अनुमान और रूपांतरण के प्रत्येक प्रश्न को शामिल नहीं किया गया है किसी भी तरह से। जैसा कि पहले कहा गया है, जहां भी संभव हो, आप ज्ञात डेटा प्रकारों के साथ स्पष्ट पैरामीटर का उपयोग करना बेहतर समझते हैं।
भाग 2 का अंत
इस श्रृंखला का अगला भाग वर्णन करता है कि कैसे सरल मानकीकरण निष्पादन योजनाओं को प्रभावित करता है।