जोड़: SQL सर्वर 2012 इस क्षेत्र में कुछ बेहतर प्रदर्शन दिखाता है, लेकिन नीचे दिए गए विशिष्ट मुद्दों से निपटने के लिए प्रतीत नहीं होता है। यह स्पष्ट रूप से अगले प्रमुख संस्करण बाद . में तय किया जाना चाहिए SQL सर्वर 2012!
आपकी योजना से पता चलता है कि सिंगल इंसर्ट पैरामीटरयुक्त प्रक्रियाओं (संभवतः ऑटो पैरामीटरयुक्त) का उपयोग कर रहे हैं, इसलिए इनके लिए पार्स/संकलन समय न्यूनतम होना चाहिए।
मैंने सोचा कि मैं इसे थोड़ा और देखूंगा, हालांकि एक लूप (स्क्रिप्ट) सेट अप करें और VALUES
की संख्या को समायोजित करने का प्रयास किया। खंड और संकलन समय की रिकॉर्डिंग।
फिर मैंने प्रति खंड औसत संकलन समय प्राप्त करने के लिए संकलन समय को पंक्तियों की संख्या से विभाजित किया। परिणाम नीचे हैं
250 तक VALUES
. तक संकलन समय प्रस्तुत करने वाले खंड / खंडों की संख्या में थोड़ा ऊपर की ओर रुझान है लेकिन कुछ भी नाटकीय नहीं है।
लेकिन तभी अचानक बदलाव आ जाता है।
डेटा का वह भाग नीचे दिखाया गया है।
+------+----------------+-------------+---------------+---------------+
| Rows | CachedPlanSize | CompileTime | CompileMemory | Duration/Rows |
+------+----------------+-------------+---------------+---------------+
| 245 | 528 | 41 | 2400 | 0.167346939 |
| 246 | 528 | 40 | 2416 | 0.162601626 |
| 247 | 528 | 38 | 2416 | 0.153846154 |
| 248 | 528 | 39 | 2432 | 0.157258065 |
| 249 | 528 | 39 | 2432 | 0.156626506 |
| 250 | 528 | 40 | 2448 | 0.16 |
| 251 | 400 | 273 | 3488 | 1.087649402 |
| 252 | 400 | 274 | 3496 | 1.087301587 |
| 253 | 400 | 282 | 3520 | 1.114624506 |
| 254 | 408 | 279 | 3544 | 1.098425197 |
| 255 | 408 | 290 | 3552 | 1.137254902 |
+------+----------------+-------------+---------------+---------------+
कैश्ड प्लान का आकार जो रैखिक रूप से बढ़ रहा था, अचानक गिर जाता है लेकिन CompileTime 7 गुना बढ़ जाता है और CompileMemory शूट हो जाता है। यह ऑटो पैरामीट्रिज्ड (1,000 मापदंडों के साथ) योजना के बीच का कट ऑफ प्वाइंट है। इसके बाद यह रैखिक रूप से कम कुशल होने लगता है (किसी निश्चित समय में संसाधित मूल्य खंडों की संख्या के संदर्भ में)।
सुनिश्चित नहीं है कि ऐसा क्यों होना चाहिए। संभावित रूप से जब यह विशिष्ट शाब्दिक मूल्यों के लिए एक योजना तैयार कर रहा है तो उसे कुछ ऐसी गतिविधि करनी चाहिए जो रैखिक रूप से स्केल न करे (जैसे सॉर्टिंग)।
यह कैश्ड क्वेरी प्लान के आकार को प्रभावित नहीं करता है जब मैंने पूरी तरह से डुप्लिकेट पंक्तियों वाली क्वेरी की कोशिश की और न ही स्थिरांक की तालिका के आउटपुट के क्रम को प्रभावित करता है (और जैसा कि आप एक ढेर समय में छँटाई में सम्मिलित कर रहे हैं वैसे भी व्यर्थ होगा, भले ही उसने किया हो)।
इसके अलावा यदि तालिका में एक क्लस्टर इंडेक्स जोड़ा जाता है तो योजना अभी भी एक स्पष्ट सॉर्ट चरण दिखाती है, इसलिए यह रन टाइम पर एक प्रकार से बचने के लिए संकलन समय पर सॉर्टिंग प्रतीत नहीं होता है।
मैंने इसे डीबगर में देखने की कोशिश की लेकिन SQL सर्वर 2008 के मेरे संस्करण के लिए सार्वजनिक प्रतीक उपलब्ध नहीं प्रतीत होते हैं, इसलिए इसके बजाय मुझे समकक्ष UNION ALL
देखना पड़ा। SQL सर्वर 2005 में निर्माण।
एक सामान्य स्टैक ट्रेस नीचे है
sqlservr.exe!FastDBCSToUnicode() + 0xac bytes
sqlservr.exe!nls_sqlhilo() + 0x35 bytes
sqlservr.exe!CXVariant::CmpCompareStr() + 0x2b bytes
sqlservr.exe!CXVariantPerformCompare<167,167>::Compare() + 0x18 bytes
sqlservr.exe!CXVariant::CmpCompare() + 0x11f67d bytes
sqlservr.exe!CConstraintItvl::PcnstrItvlUnion() + 0xe2 bytes
sqlservr.exe!CConstraintProp::PcnstrUnion() + 0x35e bytes
sqlservr.exe!CLogOp_BaseSetOp::PcnstrDerive() + 0x11a bytes
sqlservr.exe!CLogOpArg::PcnstrDeriveHandler() + 0x18f bytes
sqlservr.exe!CLogOpArg::DeriveGroupProperties() + 0xa9 bytes
sqlservr.exe!COpArg::DeriveNormalizedGroupProperties() + 0x40 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x18a bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!COptExpr::DeriveGroupProperties() + 0x146 bytes
sqlservr.exe!CQuery::PqoBuild() + 0x3cb bytes
sqlservr.exe!CStmtQuery::InitQuery() + 0x167 bytes
sqlservr.exe!CStmtDML::InitNormal() + 0xf0 bytes
sqlservr.exe!CStmtDML::Init() + 0x1b bytes
sqlservr.exe!CCompPlan::FCompileStep() + 0x176 bytes
sqlservr.exe!CSQLSource::FCompile() + 0x741 bytes
sqlservr.exe!CSQLSource::FCompWrapper() + 0x922be bytes
sqlservr.exe!CSQLSource::Transform() + 0x120431 bytes
sqlservr.exe!CSQLSource::Compile() + 0x2ff bytes
तो स्टैक ट्रेस में नामों को छोड़कर ऐसा लगता है कि स्ट्रिंग की तुलना करने में काफी समय लगता है।
यह KB आलेख इंगित करता है कि DeriveNormalizedGroupProperties
क्वेरी प्रोसेसिंग के सामान्यीकरण चरण के रूप में जाने जाने वाले से जुड़ा हुआ है
इस चरण को अब बाध्यकारी या बीजगणित कहा जाता है और यह पिछले पार्स चरण से अभिव्यक्ति पार्स ट्री आउटपुट लेता है और अनुकूलन के लिए आगे बढ़ने के लिए एक बीजगणित अभिव्यक्ति पेड़ (क्वेरी प्रोसेसर पेड़) आउटपुट करता है (इस मामले में तुच्छ योजना अनुकूलन) [रेफरी]।
मैंने एक और प्रयोग (स्क्रिप्ट) की कोशिश की जो मूल परीक्षण को फिर से चलाने के लिए था लेकिन तीन अलग-अलग मामलों को देख रहा था।
- पहला नाम और अंतिम नाम बिना किसी डुप्लीकेट के 10 वर्णों की लंबाई वाली स्ट्रिंग।
- पहला नाम और उपनाम बिना किसी डुप्लीकेट के 50 वर्णों की लंबाई के तार।
- प्रथम नाम और उपनाम सभी डुप्लीकेट के साथ लंबाई 10 वर्णों की स्ट्रिंग।
यह स्पष्ट रूप से देखा जा सकता है कि तार जितने लंबे होते हैं, चीजें उतनी ही खराब होती हैं और इसके विपरीत जितनी अधिक नकल होती है, उतनी ही बेहतर चीजें मिलती हैं। जैसा कि पहले उल्लेख किया गया डुप्लिकेट कैश्ड योजना आकार को प्रभावित नहीं करता है, इसलिए मुझे लगता है कि बीजगणित अभिव्यक्ति वृक्ष का निर्माण करते समय डुप्लिकेट पहचान की प्रक्रिया होनी चाहिए।
संपादित करें
एक जगह जहां इस जानकारी का लाभ उठाया जाता है, वह यहां @Lieven द्वारा दिखाया गया है
SELECT *
FROM (VALUES ('Lieven1', 1),
('Lieven2', 2),
('Lieven3', 3))Test (name, ID)
ORDER BY name, 1/ (ID - ID)
क्योंकि संकलन समय पर यह निर्धारित कर सकता है कि Name
कॉलम में कोई डुप्लीकेट नहीं है, यह द्वितीयक 1/ (ID - ID)
. द्वारा ऑर्डर करना छोड़ देता है रन टाइम पर एक्सप्रेशन (प्लान में सॉर्ट में केवल एक ORDER BY
. होता है कॉलम) और शून्य त्रुटि से कोई भाग नहीं उठाया जाता है। यदि तालिका में डुप्लीकेट जोड़े जाते हैं तो सॉर्ट ऑपरेटर कॉलम द्वारा दो क्रम दिखाता है और अपेक्षित त्रुटि उठाई जाती है।