SQL सर्वर - नेस्टेड गैर-नियतात्मक दृश्य स्टैक में स्ट्रिंग्स के स्थानीयकरण को संभालना


20

एक डेटाबेस की रूपरेखा बनाते समय मैं एक ऐसे दृश्य के बारे में आया जो कुछ गैर-नियतात्मक कार्यों को संदर्भित कर रहा है, जो इस एप्लिकेशन के पूल में प्रत्येक कनेक्शन के लिए प्रति मिनट 1000-2500 बार एक्सेस किया जाता है। SELECTदृश्य से एक साधारण निम्नलिखित निष्पादन योजना प्राप्त करता है:

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें

यह उस दृश्य के लिए एक जटिल योजना की तरह लगता है जिसमें हजार पंक्तियों से कम है जो हर कुछ महीनों में एक पंक्ति या दो परिवर्तन देख सकते हैं। लेकिन यह निम्नलिखित अन्य टिप्पणियों के साथ खराब हो जाता है:

  1. नेस्टेड विचार गैर-निर्धारक हैं, इसलिए हम उन्हें अनुक्रमित नहीं कर सकते हैं
  2. प्रत्येक दृश्य UDFस्ट्रिंग्स के निर्माण के लिए कई एस का संदर्भ देता है
  3. प्रत्येक UDF में UDFस्थानीय भाषाओं के लिए ISO कोड प्राप्त करने के लिए नेस्टेड s होते हैं
  4. स्टैक में देखे जाने वाले अतिरिक्त स्ट्रिंग बिल्डरों का उपयोग कर रहे हैं जो कि पेडिकेट्स के रूप में एस से लौटे हैंUDFJOIN
  5. प्रत्येक दृश्य स्टैक को एक तालिका के रूप में माना जाता है, जिसका अर्थ है कि अंतर्निहित तालिकाओं को लिखने के लिए प्रत्येक पर INSERT/ UPDATE/ DELETEट्रिगर हैं
  6. ये ट्रिगर उन विचारों पर संग्रहीत संग्रहीत प्रक्रियाओं का उपयोग CURSORSकरते हैं EXECजो इन स्ट्रिंग बिल्डिंग UDFs का अधिक संदर्भ देते हैं ।

यह मेरे लिए बहुत सड़ा हुआ लगता है, लेकिन मुझे केवल TSQL के साथ कुछ वर्षों का अनुभव है। यह भी बेहतर हो जाता है!

ऐसा प्रतीत होता है कि डेवलपर ने फैसला किया कि यह एक महान विचार था, यह सब इसलिए किया ताकि जमा किए गए कुछ सौ तार एक UDFस्कीमा-विशिष्ट से लौटे स्ट्रिंग पर आधारित अनुवाद हो सकें ।

यहाँ ढेर में से एक दृश्य है, लेकिन वे सभी समान रूप से खराब हैं:

CREATE VIEW [UserWKStringI18N]
AS
SELECT b.WKType, b.WKIndex
    , CASE
       WHEN ISNULL(il.I18NID, N'') = N''
       THEN id.I18NString
       ELSE il.I18nString
       END AS WKString
    ,CASE
       WHEN ISNULL(il.I18NID, N'') = N''
       THEN id.IETFLangCode
       ELSE il.IETFLangCode
       END AS IETFLangCode
    ,dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS') AS I18NID
    ,dbo.UserI18N_Session_Locale_Key()  AS IETFSessionLangCode
    ,dbo.UserI18N_Database_Locale_Key() AS IETFDatabaseLangCode
FROM   UserWKStringBASE b
LEFT OUTER JOIN User3StringI18N il
ON    (
il.I18NID       = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS')
AND il.IETFLangCode = dbo.UserI18N_Session_Locale_Key()
)
LEFT OUTER JOIN User3StringI18N id
ON    (
id.I18NID       = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex,N'WKS')
AND id.IETFLangCode = dbo.UserI18N_Database_Locale_Key()
)
GO

यहाँ क्यों UDFs JOINविधेय के रूप में इस्तेमाल किया जा रहा है। I18NIDस्तंभ श्रृंखलाबद्ध द्वारा बनाई है:STRING + [ + ID + | + ID + ]

इनका परीक्षण करने के दौरान, SELECTदृश्य से एक सरल ~ 309 पंक्तियों की वापसी होती है, और निष्पादित करने के लिए 900-1400ms लगते हैं। यदि मैं स्ट्रिंग्स को किसी अन्य तालिका में डंप करता हूं और उस पर एक इंडेक्स को थप्पड़ मारता है, तो वही चयन 20-75ms में रिटर्न करता है।

इसलिए, लंबी कहानी छोटी (और मुझे उम्मीद है कि आपने इस मूर्खता की कुछ सराहना की) मैं एक अच्छा सामरी होना चाहता हूं और इस उत्पाद को चलाने वाले 99% ग्राहकों के लिए फिर से लिखना चाहता हूं, जो किसी भी स्थानीयकरण का उपयोग नहीं करते हैं- -उपयोगकर्ताओं से अपेक्षा की जाती है [en-US]कि जब अंग्रेजी दूसरी / तीसरी भाषा हो तब भी लोकेल का उपयोग करें ।

चूंकि यह एक अनौपचारिक हैक है, मैं निम्नलिखित के बारे में सोच रहा हूं:

  1. मूल आधार तालिकाओं से डेटा के साफ-सुथरे रूप से जोड़े गए एक नई स्ट्रिंग तालिका बनाएं
  2. तालिका को अनुक्रमित करें।
  3. ढेर में शीर्ष स्तर के दृश्य शामिल हैं इस बात का एक प्रतिस्थापन समूह बनाना होगा NVARCHARऔर INTके लिए कॉलम WKTypeऔर WKIndexकॉलम।
  4. UDFइनमें से एक मुट्ठी को संशोधित करें जो इन विचारों को संदर्भ में शामिल होने से बचने के लिए कुछ सम्मिलित विधेयकों में जोड़ता है (हमारी सबसे बड़ी ऑडिट टेबल 500-2,000M पंक्तियाँ हैं और INTएक NVARCHAR(4000)स्तंभ में संग्रहीत करता है जो स्तंभ के खिलाफ शामिल होने के लिए उपयोग किया जाता है ) WKIndex( INT)।
  5. योजनाओं पर विचार करें
  6. विचारों में कुछ अनुक्रमणिकाएँ जोड़ें
  7. कर्सर के बजाय सेट लॉजिक का उपयोग करके विचारों पर ट्रिगर का पुनर्निर्माण करें

अब, मेरे वास्तविक प्रश्न:

  1. क्या एक दृश्य के माध्यम से स्थानीयकृत तार को संभालने के लिए एक सर्वोत्तम अभ्यास विधि है?
  2. UDFस्टब के रूप में उपयोग के लिए कौन से विकल्प मौजूद हैं ? (मैं VIEWप्रत्येक स्कीमा मालिक के लिए एक विशिष्ट लिख सकता हूं और विभिन्न प्रकार के UDFस्टब्स पर निर्भर होने के बजाय भाषा को हार्ड-कोड कर सकता हूं )
  3. क्या इन दृश्यों को पूरी तरह से नेस्टेड UDFएस को पूरी तरह से निर्धारित करके और फिर स्टैक को नजरअंदाज करके निर्धारक बनाया जा सकता है ?

5
स्केलर UDF को इनलाइन टेबल मान UDF में बदलने का प्रयास करें । अपनी UDFपरिभाषा भी पोस्ट करें । इसके अलावा, T-SQL यूज़र-डिफ़ाइंड फ़ंक्शंस का
परिजन शाह

क्या यह आपकी किसी भी तरह से मदद करता है? stackoverflow.com/questions/316780/…
stacylaray

जवाबों:


1

दिए गए कोड को देखते हुए, हम कह सकते हैं,

  • सबसे पहले, यह एक दृश्य नहीं होना चाहिए, लेकिन यह एक संग्रहित प्रक्रिया होनी चाहिए, क्योंकि यह सिर्फ एक तालिका से पढ़ना नहीं है, लेकिन यह यूटीएफ का उपयोग करता है।
  • दूसरा, यूडीएफ को एक ही कॉलम के लिए अक्सर नहीं बुलाया जाना चाहिए। यहाँ, यह एक बार चयन में कहा जाता है

    ,dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS') AS I18NID 

    और शामिल होने का दूसरा समय

    .IETFLangCode = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS')

एक अस्थायी तालिका में मान उत्पन्न कर सकते हैं या शामिल होने से पहले उन मूल्यों को प्राप्त करने के लिए CTE (सामान्य तालिका अभिव्यक्ति) का उपयोग कर सकते हैं।

मैंने एक नमूना यूएसपी तैयार किया है जो कुछ सुधार प्रदान करेगा:

CREATE PROCEDURE usp_UserWKStringI18N
AS
BEGIN
    -- Do operation using UDF 
    SELECT b.WKType
        ,b.WKIndex
        ,dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS') AS I18NID
        ,dbo.UserI18N_Session_Locale_Key() AS IETFSessionLangCode
        ,dbo.UserI18N_Database_Locale_Key() AS IETFDatabaseLangCode
    INTO #tempTable
    FROM UserWKStringBASE b;

    -- Now final Select
    SELECT b.WKType
        ,b.WKIndex
        ,CASE 
            WHEN ISNULL(il.I18NID, N'') = N''
                THEN id.I18NString
            ELSE il.I18nString
            END AS WKString
        ,CASE 
            WHEN ISNULL(il.I18NID, N'') = N''
                THEN id.IETFLangCode
            ELSE il.IETFLangCode
            END AS IETFLangCode
        ,b.I18NID
        ,b.IETFSessionLangCode
        ,b.IETFDatabaseLangCode
    FROM #tempTable b
    LEFT OUTER JOIN User3StringI18N il
        ON il.I18NID = b.I18NID
            AND il.IETFLangCode = b.IETFSessionLangCode
    LEFT OUTER JOIN User3StringI18N id
        ON id.I18NID = b.I18NID
            AND id.IETFLangCode = b.IETFDatabaseLangCode
END

कृपया यह प्रयास करें


नमस्कार MarmiK, इस पोस्ट को देखने के लिए समय निकालने के लिए धन्यवाद। यह दुर्भाग्य से एक दृश्य है (नेस्टेड दृश्यों की एक श्रृंखला में) इसलिए इसे संग्रहीत प्रक्रिया में ले जाना प्रश्न से बाहर था।
गत

उस स्थिति में हम CTE को देखने में उपयोग कर सकते हैं क्योंकि व्यू में टेम्‍प टेबल की अनुशंसा नहीं की जाती है। या अस्थायी तालिका की पंक्तियों को कुछ संग्रहीत प्रक्रिया द्वारा उत्पन्न किया जा सकता है और इसे देखने के लिए कहा जा सकता है।
MarmiK
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.