2013-05-24 7 views
5

अभी मैं एक सुंदर जटिल डेटाबेस पर काम कर रहा हूं। हमारा ऑब्जेक्ट मॉडल डेटाबेस में मैप किए जाने के लिए डिज़ाइन किया गया है। हम मैन्युअल रूप से जेनरेट किए गए पीओसीओ कक्षाओं के साथ ईएफ 5 का उपयोग कर रहे हैं।इकाई फ्रेमवर्क 5 प्रदर्शन चिंताओं

सबकुछ काम कर रहा है, लेकिन प्रदर्शन के बारे में कुछ शिकायत है। मैंने कभी ईएफ के साथ प्रदर्शन की समस्या नहीं की है, इसलिए मैं सोच रहा हूं कि इस बार मैंने कुछ गलत किया है, या समस्या कहीं और रह सकती है।

मुख्य क्वेरी गतिशील पैरामीटर से बना हो सकती है।

if (parameter != null) { query = query.Where(c => c.Field == parameter); } 

इसके अलावा, कुछ जटिल और/या संयोजन मैं Albahari से LinqKit एक्सटेंशन का उपयोग कर रहा हूँ के लिए: मैं कई अगर और स्विच ब्लॉकों है कि इस तरह धारणात्मक हैं।

क्वेरी "ऑर्डर" की एक बड़ी तालिका के खिलाफ है, जिसमें वर्षों और वर्षों के डेटा शामिल हैं। हालांकि औसत उपयोग एक 2 महीने रेंज फिल्टर है।

अब जब मुख्य क्वेरी तैयार की जाती है, तो इसे Skip/Take संयोजन के साथ अंकनित किया जाता है, जहां टेक 10 तत्वों पर सेट होता है।

इसके बाद, IQueryable परतों के माध्यम से भेजा जाता है, एमवीसी परत तक पहुंचता है जहां ऑटोमैपर नियोजित होता है।

यहां, जब ऑटोमैपर फिर से शुरू होता है (और इस प्रकार क्वेरी वास्तव में निष्पादित होती है) यह नेविगेशन गुणों का एक गुच्छा कहती है, जिसमें उनके स्वयं के नेविगेशन गुण होते हैं और इसी तरह। अगर आपके पास 3 या 4 से अधिक विशिष्ट इकाइयों को शामिल करने के लिए उत्सुक लोडिंग से बचने के लिए ईएफ सिफारिशों के अनुसार सब कुछ आलसी हो रहा है। (10 अधिकतम) आदेश

  • इनमें से कुछ उनके अधीन अन्य नेविगेशन (स्थानीयकरण संस्थाओं)
  • आदेश है के तहत
    • कई नेविगेशन गुण

      • आदेश: मेरी परिदृश्य कुछ इस तरह है विवरण (प्रति ऑर्डर के कई ऑर्डर विवरण)
        • प्रत्येक ऑर्डर विवरण के तहत कई नेविगेशन गुण
          • इनमें से कुछ उनके अधीन अन्य नेविगेशन (स्थानीयकरण संस्थाओं) है

    यह आसानी से एक भी प्रदान की गई "पृष्ठ" के लिए 300+ प्रश्नों की कुल की ओर जाता है। उन प्रश्नों में से प्रत्येक बहुत तेजी से होता है, कुछ मिलीसेकेंड में चल रहा है, लेकिन अभी भी वहाँ 2 मुख्य चिंताएं हैं: इस प्रकार अधिक समय

  • लेने परिणामस्वरूप,

    • आलसी लोड गुण अनुक्रम में कहा जाता है और नहीं parallelized पिछले बिंदु के, प्रत्येक क्वेरी के बीच कुछ मृत समय है, क्योंकि डेटाबेस को एसक्यूएल प्राप्त करना है, इसे चलाएं, इसे वापस करें और प्रत्येक क्वेरी के लिए इसे वापस करें।

    बस देखने के लिए कि यह कैसे चला गया, मैं उत्सुक लोड हो रहा है के साथ एक ही क्वेरी करने की कोशिश की है, और जैसा कि मैंने भविष्यवाणी की यह एक से अधिक 7K लाइनों (हाँ, सात हजारों) और के एक अनुवाद एसक्यूएल के साथ एक कुल आपदा थी, समग्र रूप से अधिक धीमी गति से।

    अब मुझे लगता है कि इस परिदृश्य के लिए ईएफ और लिंक सही विकल्प नहीं हैं। कुछ लोग कह रहे हैं कि यदि वे एक संग्रहीत प्रक्रिया लिखना चाहते थे जो सभी आवश्यक डेटा प्राप्त करता है, तो यह कई गुना तेजी से चलता है। मुझे विश्वास नहीं है कि यह सच है, और हम सभी संबंधित इकाइयों के स्वचालित भौतिककरण को खो देंगे।

    मैं कुछ चीजें मैं जैसे, सुधार करने के लिए कर सकता है के बारे में सोचा:,

    • टेबल बंटवारे चयनित स्तंभों
    • वस्तु पर नज़र रखने को बंद कर दें कम करने के लिए के रूप में इस परिदृश्य केवल पढ़ने के लिए (ट्रैक न किए गए इकाइयां)

    इन सभी के साथ, मुख्य शिकायत यह है कि परिणाम पृष्ठ (एमवीसी 4 में किया गया) बहुत धीरे-धीरे प्रस्तुत करता है, और कुछ निदान के बाद यह सभी "सर्वर समय" और "नेटवर्क टाइम" नहीं लगता है सर्वर समय के 8 से 12 सेकंड के बारे में।

    मेरे अनुभव से, यह हो रहा नहीं किया जाना चाहिए। मैं अगर मैं एक गलत तरीके से इस प्रश्न की जरूरत आ रहा हूँ सोच रहा हूँ, या अगर मैं कुछ और (शायद एक बुरा कॉन्फ़िगर किया गया आईआईएस सर्वर, वरना मैं सच में पता कर रहा हूँ कुछ भी) के लिए मेरा ध्यान बारी करने के लिए है। कहने के लिए सुई, डेटाबेस के सूचकांक ठीक है, हमारे डीबीए द्वारा बहुत सावधानी से जांच की।

    किसी को भी किसी भी टिप, सलाह, सबसे अच्छा अभ्यास मैं इस बारे में याद कर रहा हूँ, या बस मुझे इस स्थिति के लिए लेज़ी लोड हो रहा है साथ एफई का उपयोग करने में बता सकता है कि मैं मर गलत हूँ है तो अगर ... आप सभी का स्वागत करते हैं ।

  • +0

    एफडब्ल्यूआईडब्ल्यू, मैं अपने स्वयं के ओआरएम को वर्षों से (ईएफ अस्तित्व से पहले) बनाए रख रहा हूं (काफी खुशी से)। मैंने पाया है कि जटिल भार शामिल होने पर स्वचालन टूटना शुरू हो जाता है। मैं आमतौर पर एक जटिल ऑब्जेक्ट पेड़ के लिए आवश्यक डेटा प्राप्त करने के लिए एक संग्रहित प्रक्रिया लिखता हूं, और उसके बाद इसे उन मददगारों के पास भेजता हूं जो तत्काल/मानचित्रण को स्वचालित करते हैं। इसमें कोड का एक बड़ा सौदा शामिल नहीं है और - ठीक से किया गया - यह बहुत तेज़ होगा। यहां तक ​​कि यदि आपके 300 कॉल जल्दी से निष्पादित होते हैं, तो क्या आप वास्तव में 300 कॉल चाहते हैं जब 1 करेगा? मुझे तेजी से नेटवर्क पर एक चतुर रिश्ते के साथ कोई समस्या नहीं है, लेकिन यह अत्यधिक है। –

    +0

    तो मुझे लौटाई गई एसक्यूएल से प्रत्येक इकाई को मूर्त रूप देने के लिए कोड को मैन्युअल रूप से संयोजित करना होगा। इस डेटाबेस की इकाइयां/सारणी 100 के आसपास हैं। क्या आप वाकई यह एक सुविधाजनक समाधान होगा? क्योंकि यह मुझे नहीं लगता है। –

    +0

    मैं कोड प्रोफाइलिंग और सटीक हॉटस्पॉट की पहचान करने का सुझाव दूंगा। आप कहते हैं कि यह "सर्वर समय" है; एक प्रोफाइलर संलग्न करें (उदा। वीएस में से एक) और पता लगाएं कि यह समय कहां खर्च कर रहा है। और हां, संग्रहित प्रक्रिया को बनाए रखना जो दर्जनों टेबल लौटाता है चुनौतीपूर्ण हो सकता है (हालांकि स्कीमा नहीं बदले तो वह बुरा नहीं है)। मुझे उम्मीद है कि भौतिकरण अभी भी कुछ हद तक स्वचालित हो सकता है (सुनिश्चित नहीं है कि ईएफ में स्वचालित लोड के साथ मैन्युअल कॉल मिश्रण करने के लिए क्या क्षमताएं हैं)। –

    उत्तर

    0

    एक बात पर विचार करना, एफई निश्चित रूप से बहुत जल्दी विकास समय बनाने में मदद करता। हालांकि, अगर आप याद रखना चाहिए कि जब आप DB से डेटा के बहुत सारे के लिए लौट रहे, कि एफई गतिशील एसक्यूएल उपयोग कर रहा है। इसका मतलब है कि ईएफ होना चाहिए 1. एसक्यूएल, 2. एसक्यूएल सर्वर बनाएँ, फिर निष्पादन योजना बनाने की आवश्यकता है। प्रश्न चलाने से पहले ऐसा होता है।

    संग्रहीत प्रक्रियाओं का उपयोग करते समय, SQL सर्वर निष्पादन योजना को कैश कर सकता है (जिसे प्रदर्शन के लिए संपादित किया जा सकता है), जो इसे ईएफ का उपयोग करने से तेज़ बनाता है। लेकिन ... आप हमेशा अपनी संग्रहित प्रो बना सकते हैं और फिर इसे ईएफ से निष्पादित कर सकते हैं। किसी भी जटिल प्रक्रियाओं या प्रश्नों को मैं संग्रहीत प्रोसेस में परिवर्तित कर दूंगा और फिर ईएफ से कॉल करूंगा। फिर आप अपने प्रदर्शन लाभ (ओं) देख सकते हैं और वहां से पुनर्मूल्यांकन कर सकते हैं।

    +1

    एक नोट के रूप में, मेरा मानना ​​है कि एफई प्रश्नों यह बनाता है कैश करने के लिए प्रत्येक अनुरोध के साथ पूरा अभिव्यक्ति पेड़ यात्रा करने के लिए होने से बचने की कोशिश करता है। एसक्यूएल सर्वर निश्चित रूप से निष्पादन योजना को कैश करने का प्रयास करेगा, भले ही क्वेरी संग्रहीत प्रक्रिया में न हो। हालांकि, ओपी के प्रयोजनों के लिए, एक संग्रहित प्रो बहुत अच्छी तरह से सही समाधान हो सकता है। एफई कैशिंग करता है, लेकिन है कि एसक्यूएल सर्वर कैशिंग की तुलना में बहुत अलग है –

    +0

    है। उदाहरण के लिए ईएफ SQL सर्वर निष्पादन योजना को कैश नहीं कर सकता है। और बहुत सारे डेटा लौटने वाले प्रश्नों के लिए आपको आश्चर्य होगा कि इससे कितना अंतर हो सकता है। जब मैं बड़े पैमाने पर आवेदन पत्र समय एफई की मैं सबसे लिखते हैं, लेकिन जब गति महत्वपूर्ण है (मैं वित्त में काम करते हैं), संग्रहीत procs आवश्यक हैं। – Jeff

    +1

    मुझे मतभेदों से अवगत है ... मैं 2 अलग-अलग चीजों के बारे में बात कर रहा हूं। क्या मैंने कहा 1) मुझे लगता है कि एफई कैश (बहुत महंगा) अभिव्यक्ति SQL क्वेरी बनाने के लिए और 2) एसक्यूएल सर्वर क्वेरी खुद का अनुकूलन करने की कोशिश करेंगे इस्तेमाल किया पेड़ की ट्रेवर्सल, भले ही वह एक संग्रहीत proc में नहीं है था । फिर भी, मुझे लगता है कि हम मौलिक दृष्टिकोण पर सहमत हैं (प्रश्न पर मेरी टिप्पणियां देखें)। जटिल वृक्ष आबादी अक्सर एक कस्टम संग्रहित प्रक्रिया बनाने के लिए एक बहुत अच्छा कारण है। एक स्वचालित प्रणाली के लिए इस तरह के डेटा को लोड करने के सबसे इष्टतम तरीके का अनुमान लगाने के लिए बहुत मुश्किल है। –

    2

    अपने विचारों के लिए डेटा प्राप्त करने के लिए एक कुशल लेकिन सरल एसक्यूएल क्वेरी के बारे में सोचने का प्रयास करें।

    क्या यह भी संभव है?

    यदि नहीं, तो (denormalize) को अपने टेबल को विघटित करने का प्रयास करें ताकि डेटा प्राप्त करने के लिए कम जुड़ने की आवश्यकता हो। साथ ही, डेटा पुनर्प्राप्ति को तेज करने के लिए टेबल कॉलम पर कुशल अनुक्रमणिका हैं?

    यदि हां, तो ईएफ भूल जाएं, संग्रहित प्रक्रिया लिखें और डेटा प्राप्त करने के लिए इसका उपयोग करें।

    चयनित प्रश्नों के लिए ट्रैकिंग बंद करना केवल पढ़ने-योग्य परिदृश्य के लिए जरूरी है।मेरी संख्या पर एक नज़र डालें:

    http://netpl.blogspot.com/2013/05/yet-another-orm-micro-benchmark-part-23_15.html

    आप देख सकते हैं, पर नज़र रखने और notracking परिदृश्य के बीच का अंतर महत्वपूर्ण है।

    मैं उत्सुक लोडिंग के साथ प्रयोग करता हूं लेकिन हर जगह नहीं (इसलिए आप 7k लाइन लंबी क्वेरी के साथ समाप्त नहीं होते हैं) लेकिन चयनित उप-श्रेणियों में।

    +0

    कम से कम कहना दिलचस्प है। मुझे अभी भी आश्चर्य है कि मॉडेल फर्स्ट पहले कोड से तेज क्यों है। वैसे भी डेटाबेस में बदलाव नहीं एक विकल्प के रूप में मुझे लगता है कि कॉल करने के लिए की स्थिति में नहीं हूँ, यह भी कहा कि डेटाबेस एक केवल पढ़ने के लिए डेटाबेस, एक और एसक्यूएल, जो नौकरियों है कि एक 20 साल पुराने AS400 से डेटा लाने की आबादी है से नजर आता है। आपको तस्वीर मिलती है :) –

    +0

    कोड पहले आंतरिक रूप से मॉडल का उपयोग करता है, इसलिए यह समझने के लिए चीजों को लपेटने की कीमत का भुगतान करता है। –

    +0

    ट्रैकिंग बंद करने का प्रयास किया, लेकिन लगभग कुछ भी नहीं बदला। हम मुख्य इकाई से एक समय में केवल 10 परिणाम प्राप्त करने के लिए Skip/Take का उपयोग कर रहे हैं। मैंने ऑटोमैपर के परिवर्तन को समानांतर करने की भी कोशिश की, 1.5 सेकंड प्राप्त किए, लेकिन अभी भी पास नहीं है। एक दृश्य या एक sproc के साथ भी denormalizing, गलत लगता है। हमने पुराने डेटा से हमारी डेटा संरचना को सामान्य बनाने के लिए बहुत सारे काम किए हैं, इसलिए अब इसे इसे डिमॉर्मलाइज्ड करने के लिए पूछना होगा, फिर इसे सामान्यीकृत ऑब्जेक्ट्स में कनवर्ट करने के लिए मैन्युअल मैपिंग कोड का एक गुच्छा लिखें? Aw :( –

    4

    बहुत जटिल क्वेरी के लिए जो पदानुक्रमित डेटा लाता है, संग्रहीत प्रोसेस आमतौर पर LINQ/EF पर प्रदर्शन-वार की सहायता नहीं करेंगे यदि आप सही दृष्टिकोण लेते हैं। जैसा कि आपने ध्यान दिया है, ईएफ (आलसी और उत्सुक लोडिंग) के साथ "बॉक्स के बाहर" विकल्प दो परिदृश्य में अच्छी तरह से काम नहीं करते हैं। हालांकि, अभी भी इसे अनुकूलित करने के कई अच्छे तरीके हैं:

    (1) स्मृति में इकाइयों का एक गुच्छा पढ़ने और फिर ऑटोमैपर के माध्यम से मैपिंग करने के बजाय, जहां संभव हो वहां सीधे "ऑटोमैपिंग" करें। उदाहरण के लिए:

    var mapped = myOrdersQuery.Select(o => new OrderInfo { Order = o, DetailCount = o.Details.Count, ... }) 
        // by deferring the load until here, we can bring only the information we actually need 
        // into memory with a single query 
        .ToList(); 
    

    यह दृष्टिकोण वास्तव में अच्छी तरह से काम करता है यदि आपको केवल अपने जटिल पदानुक्रम में फ़ील्ड का सबसेट चाहिए। साथ ही, पदानुक्रमित डेटा का चयन करने की ईएफ की क्षमता संग्रहित प्रोसेस का उपयोग करने से कहीं अधिक आसान बनाती है यदि आपको फ्लैट टैब्यूलर डेटा की तुलना में कुछ अधिक जटिल वापस करने की आवश्यकता है।

    (2) हाथ से कई LINQ प्रश्नों को चलाएं और परिणामों को स्मृति में इकट्ठा करें।

    // read with AsNoTracking() since we'll be manually setting associations 
    var myOrders = myOrdersQuery.AsNoTracking().ToList(); 
    var orderIds = myOrders.Select(o => o.Id); 
    var myDetails = context.Details.Where(d => orderIds.Contains(d.OrderId)).ToLookup(d => d.OrderId); 
    // reassemble in memory 
    myOrders.ForEach(o => o.Details = myDetails[o.Id].ToList()); 
    

    यह वास्तव में अच्छी तरह से काम करता है जब आप सभी डेटा की जरूरत है और अभी भी जितना संभव हो उतना एफई भौतिकीकरण के लाभ लेना चाहते हैं: उदाहरण के लिए। ध्यान दें कि, ज्यादातर मामलों में एक संग्रहित प्रो दृष्टिकोण इस से बेहतर नहीं हो सकता है (यह कच्चे एसक्यूएल के साथ काम कर रहा है, इसलिए इसे कई टैब्यूलर प्रश्नों को चलाने के लिए है) लेकिन LINQ में पहले से लिखे गए तर्क का पुन: उपयोग नहीं कर सकता है।

    (3) मैन्युअल रूप से नियंत्रित करने के लिए शामिल करें() का उपयोग करें कि कौन से संगठन उत्सुक हैं। कुछ संगठनों के लिए ईएफ लोडिंग का लाभ उठाने के लिए इसे # 2 के साथ जोड़ा जा सकता है जबकि आपको दूसरों को मैन्युअल रूप से लोड करने के लिए लचीलापन मिलता है।

    0

    कुछ मामलों में, आप संकलित क्वेरी को बेहतर बनाने के लिए संकलित क्वेरी MSDN का उपयोग कर सकते हैं। विचार यह है कि यदि आपके पास एक सामान्य क्वेरी है जो कई बार चलाती है जो अलग-अलग पैरामीटर के साथ एक ही SQL कॉल उत्पन्न कर सकती है, तो आप क्वेरी टाई को पहली बार संकलित करते हैं, फिर इसे एक प्रतिनिधि के रूप में पास करें, एंटीटी फ्रेमवर्क के ओवरहेड को हटा दें, प्रत्येक आगामी कॉल के लिए एसक्यूएल उत्पन्न करना।

    संबंधित मुद्दे