क्या एंटिटी फ्रेमवर्क उच्च-यातायात वेबसाइटों के लिए उपयुक्त है?


176

क्या एंटिटी फ्रेमवर्क 4 सार्वजनिक वेबसाइट के लिए संभावित रूप से 1000 हिट / सेकंड के साथ एक अच्छा समाधान है?

मेरी समझ में ईएफ ज्यादातर छोटी या इंट्रानेट वेबसाइटों के लिए एक व्यवहार्य समाधान है, लेकिन एक लोकप्रिय सामुदायिक वेबसाइट (मुझे पता है कि एसओ LINQ एसक्यूएल का उपयोग कर रहा है, जैसे कुछ के लिए आसानी से स्केल नहीं होगा, लेकिन .. मैं अधिक उदाहरण / प्रमाण चाहूंगा। ..)

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

पहले ही, आपका बहुत धन्यवाद।


1
आप स्केलिंग को नहीं समझते हैं। जब आप 10x क्षमता जोड़ते हैं तो स्केलिंग का अर्थ है 10x थ्रूपुट प्राप्त करना। ईएफ ऐसा होने से क्यों रोकेगा? यह किसी भी डेटाबेस वर्कलोड के लिए एक निरंतर कारक ओवरहेड जोड़ता है।
usr

जवाबों:


152

यह इस बात पर निर्भर करता है कि आपको कितनी अमूर्तता की आवश्यकता है । सब कुछ एक समझौता है; उदाहरण के लिए, एफई और NHibernate रोचक और विदेशी मॉडल में डेटा का प्रतिनिधित्व करने के लिए अनेक विकल्प उपलब्ध कराता परिचय - लेकिन एक परिणाम के रूप में वे कर भूमि के ऊपर जोड़ें। ध्यान देने योग्य ओवरहेड।

यदि आपको डेटाबेस प्रदाताओं और विभिन्न प्रति-ग्राहक तालिका लेआउट के बीच स्विच करने में सक्षम होने की आवश्यकता नहीं है , और यदि आपका डेटा मुख्य रूप से पढ़ा जाता है , और यदि आपको EF, SSRS में समान मॉडल का उपयोग करने में सक्षम होने की आवश्यकता नहीं है , ADO.NET डेटा सर्विसेज, आदि - तो अगर आप अपने महत्वपूर्ण उपाय के रूप में पूर्ण प्रदर्शन चाहते हैं तो आप डापर को देखने से भी बदतर कर सकते हैं । LINQ-to-SQL और EF दोनों के आधार पर किए गए हमारे परीक्षणों में, हम पाते हैं कि EF कच्चे रीड परफॉर्मेंस के मामले में काफी धीमा है, संभवतया एब्सट्रैक्शन लेयर्स (स्टोरेज मॉडल आदि के बीच) और मटीरियलाइजेशन के कारण।

यहां SO पर, हम कच्चे प्रदर्शन के बारे में जुनूनी-बाध्यकारी हैं, और हम गति प्राप्त करने के लिए कुछ अमूर्त खोने के विकास हिट को लेने के लिए खुश हैं। जैसे, डेटाबेस को क्वेरी करने के लिए हमारा प्राथमिक टूल डापर है । यह भी हमें हमारे पहले से मौजूद LINQ-to-SQL मॉडल का उपयोग करने की अनुमति देता है, लेकिन बस: यह तेजी से ढेर है। प्रदर्शन परीक्षणों में, यह अनिवार्य रूप से सभी ADO.NET कोड (पैरामीटर, डेटा-रीडर आदि) को मैन्युअल रूप से लिखने के समान ही है, लेकिन कॉलम नाम गलत होने के जोखिम के बिना। हालांकि, यह एसक्यूएल आधारित है (हालांकि यह SPROCs का उपयोग करने के लिए खुश है अगर वह आपका चुना जहर है)। इस का लाभ यह है कि है कोई अतिरिक्त संसाधन शामिल है, लेकिन यह है कि जो लोग एसक्यूएल की तरह के लिए एक प्रणाली। जिस पर मैं विचार करता हूं: बुरी बात नहीं!

एक विशिष्ट क्वेरी, उदाहरण के लिए, हो सकती है:

int customerId = ...
var orders = connection.Query<Order>(
    "select * from Orders where CustomerId = @customerId ",
    new { customerId }).ToList();

जो सुविधाजनक है, इंजेक्शन-सुरक्षित, आदि - लेकिन डेटा-रीडर गू के टन के बिना। ध्यान दें कि जब यह जटिल संरचनाओं को लोड करने के लिए क्षैतिज और ऊर्ध्वाधर दोनों विभाजनों को संभाल सकता है, तो यह आलसी-लोडिंग का समर्थन नहीं करेगा (लेकिन: हम बहुत स्पष्ट लोडिंग के बड़े प्रशंसक हैं - कम आश्चर्य)।

इस उत्तर में ध्यान दें कि मैं यह नहीं कह रहा हूं कि ईएफ उच्च मात्रा के काम के लिए उपयुक्त नहीं है ; बस: मुझे पता है कि डपर इसके ऊपर है।


25
डेपर के लिए +1। रीड मॉडल के लिए एक जटिल ओआरएम का उपयोग करना सिर्फ अनावश्यक है। अब हम जो दृष्टिकोण अपनाते हैं, वह हमारे डोमेन मॉडल (जहां फैंसी ओआरएम सामान वास्तव में उपयोगी है) के लिए ओआरएम का उपयोग करना है और हमारे रीड मॉडल के लिए डैपर है। यह सुपर फास्ट एप्लिकेशन के लिए बनाता है।

2
@Marc, आप महान जवाब के लिए धन्यवाद - मैं अंत में विश्वास के साथ अपना निर्णय ले सकता हूं! बाद में अधिक विस्तार से निश्चित रूप से डापर में देखेंगे। वास्तव में पसंद है कि यह कैसे सिर्फ एक फ़ाइल है :)

3
मैंने अपना ORM लिखा। ये धीमा है। मैंने डैपर को देखा और उसे पसंद किया। अब मैं अपने सभी रीड्स और आवेषण के लिए अपने स्वयं के ओआरएम (जो एफके, लेनदेन और सभी अच्छे सामान का समर्थन करता है) के लिए डैपर का उपयोग करता हूं। इसका सबसे आसान पठनीय कोड मैंने कभी लिखा है।

2
@ acidzombie24 डैपर लेन-देन का समर्थन करता है, और डॅपर (नगेट का हिस्सा नहीं) का कंट्राब वाला हिस्सा इंसर्ट आदि विकल्प हासिल कर रहा है। पूर्णता के लिए सिर्फ उल्लेख। मुझे खुशी है कि डॅपर काम कर रहा था।
मार्क Gravell

1
@ किसी भी विषय पर मैंने कभी भी वीडियो कोर्स नहीं किया है; वहाँ कुछ वीडियो हैं, लेकिन मेरे द्वारा नहीं। मैं एक प्रश्न के लिखित शब्द व्यक्ति हो जाते हैं
मार्क Gravell

217

यह सवाल "जो मुझे ओआरएम का उपयोग करना चाहिए" वास्तव में एक विशाल हिमशैल के टिप को लक्षित कर रहा है जब यह बड़े पैमाने पर आवेदन में समग्र डेटा एक्सेस रणनीति और प्रदर्शन अनुकूलन की बात आती है।

निम्नलिखित बातें (सब के सब मोटे तौर पर महत्व के क्रम में) प्रवाह क्षमता को प्रभावित करने जा रहे हैं, और उन सभी वहाँ प्रमुख ORM चौखटे के सबसे द्वारा नियंत्रित किया जाता है (कभी कभी अलग अलग तरीकों से):

  1. डेटाबेस डिजाइन और रखरखाव

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

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

    यदि आप उन सुविधाओं का लाभ नहीं उठाते हैं जो डेटाबेस आपको देता है, जैसे पृष्ठ संपीड़न, FILESTREAMभंडारण (बाइनरी डेटा के लिए), SPARSEकॉलम, hierarchyidपदानुक्रम के लिए, और इसी तरह (सभी SQL सर्वर उदाहरण), तो आप कहीं भी पास नहीं देखेंगे प्रदर्शन जिसे आप देख सकते हैं।

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

  2. उत्सुक बनाम आलसी लोड हो रहा है

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

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

    "शुद्ध एसक्यूएल" (यानी कच्चे ADO.NET प्रश्न / संग्रहीत प्रक्रियाओं) का उपयोग करने का एक दिलचस्प लाभ यह है कि यह मूल रूप से आपको यह सोचने के लिए मजबूर करता है कि किसी दिए गए स्क्रीन या पृष्ठ को प्रदर्शित करने के लिए क्या डेटा आवश्यक है। ORMs और आलसी लोडिंग सुविधाओं नहीं है को रोकने के ऐसा करने से आप, लेकिन वे करते हैं आप होने के लिए ... अच्छी तरह से, अवसर देते हैं आलसी , और गलती से प्रश्नों आप पर अमल की संख्या में विस्फोट। इसलिए आपको अपने ORM की उत्सुक-लोडिंग सुविधाओं को समझने की आवश्यकता है और किसी भी पृष्ठ अनुरोध के लिए सर्वर को भेजे जाने वाले प्रश्नों की संख्या के बारे में सतर्क रहें।

  3. कैशिंग

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

    L1 कैश L2S और EF में काफी अपारदर्शी है, आपको भरोसा है कि यह काम कर रहा है। NHibernate इसके बारे में अधिक स्पष्ट है ( Get/ Loadबनाम Query/ QueryOver)। फिर भी, जब तक आप जितना संभव हो आईडी द्वारा क्वेरी करने का प्रयास करते हैं, आपको यहां ठीक होना चाहिए। बहुत सारे लोग L1 कैश के बारे में भूल जाते हैं और बार-बार एक ही इकाई को अपनी आईडी (यानी एक लुकअप) के अलावा किसी अन्य चीज़ से बार-बार देखते हैं। यदि आपको ऐसा करने की आवश्यकता है, तो आपको भविष्य के लुकअप के लिए आईडी या यहां तक ​​कि पूरी इकाई को सहेजना चाहिए।

    एक स्तर 2 कैश ("क्वेरी कैश") भी है। NHibernate में यह बिल्ट-इन है। Linq to SQL और Entity Framework ने प्रश्नों को संकलित किया है , जो कि क्वेरी एक्सप्रेशन को स्वयं संकलित करके ऐप सर्वर लोड को काफी कम करने में मदद कर सकता है, लेकिन यह डेटा को कैश नहीं करता है। Microsoft इसे डेटा-एक्सेस चिंता के बजाय एक एप्लिकेशन चिंता का विषय मानता है, और यह L2S और EF दोनों का एक प्रमुख कमजोर बिंदु है। कहने की जरूरत नहीं है कि यह "रॉ" एसक्यूएल का एक कमजोर बिंदु भी है। मूल रूप से NHibernate के अलावा किसी भी ORM के साथ वास्तव में अच्छा प्रदर्शन पाने के लिए, आपको अपने स्वयं के कैशिंग फाकेड को लागू करने की आवश्यकता है।

    EF4 के लिए एक L2 कैश "एक्सटेंशन" भी है जो ठीक है , लेकिन एप्लिकेशन-स्तर कैश के लिए वास्तव में एक थोक प्रतिस्थापन नहीं है।

  4. क्वेरी की संख्या

    रिलेशनल डेटाबेस डेटा के सेट पर आधारित होते हैं । वे कम समय में बड़ी मात्रा में डेटा का उत्पादन करने में वास्तव में अच्छे हैं , लेकिन वे क्वेरी विलंबता के मामले में कहीं भी अच्छे नहीं हैं क्योंकि हर कमांड में एक निश्चित मात्रा में ओवरहेड शामिल है। एक अच्छी तरह से डिज़ाइन किया गया ऐप इस DBMS की ताकत के लिए खेलना चाहिए और प्रश्नों की संख्या को कम करने और प्रत्येक में डेटा की मात्रा को अधिकतम करने का प्रयास करना चाहिए।

    अब मैं पूरे डेटाबेस को क्वेरी करने के लिए नहीं कह रहा हूं जब आपको केवल एक पंक्ति की आवश्यकता होती है। अगर आप की जरूरत है, जो मैं कह रहा हूँ है Customer, Address, Phone, CreditCard, और Orderएक ही पृष्ठ प्रदर्शित करने के लिए एक ही समय में सभी पंक्तियों, तो आप चाहिए पूछना , एक ही समय में उन सब के लिए अलग से प्रत्येक क्वेरी को निष्पादित नहीं है। कभी-कभी यह उससे भी बदतर होता है, आप एक ही Customerबार में 5 बार एक ही रिकॉर्ड करने वाले कोड को देखेंगे , पहले प्राप्त करने के लिए Id, फिर Name, फिर EmailAddress, फिर ... यह हास्यास्पद रूप से अक्षम है।

    यहां तक ​​कि अगर आपको कई प्रश्नों को निष्पादित करने की आवश्यकता होती है, जो सभी डेटा के पूरी तरह से अलग-अलग सेटों पर काम करते हैं, तो यह आम तौर पर सभी को एक "स्क्रिप्ट" के रूप में डेटाबेस में भेजने के लिए अधिक कुशल होता है और इसके कई परिणाम सेट लौटाते हैं। यह वह ओवरहेड है जिसके साथ आप चिंतित हैं, डेटा की कुल राशि नहीं।

    यह सामान्य ज्ञान की तरह लग सकता है लेकिन आवेदन के विभिन्न भागों में निष्पादित होने वाले सभी प्रश्नों का ट्रैक खोना वास्तव में बहुत आसान है; आपका सदस्यता प्रदाता उपयोगकर्ता / भूमिका तालिकाओं पर सवाल उठाता है, आपका हैडर एक्शन खरीदारी की टोकरी पर सवाल उठाता है, आपकी मेनू कार्रवाई साइट मानचित्र तालिका पर सवाल उठाता है, आपकी साइडबार कार्रवाई में फ़ीचर्ड उत्पाद सूची पर सवाल उठाता है, और फिर शायद आपके पृष्ठ को कुछ अलग स्वायत्त क्षेत्रों में विभाजित किया जाता है जो ऑर्डर इतिहास, हाल ही में देखे गए, श्रेणी और सूची सारणी को अलग से क्वेरी करें, और इससे पहले कि आप इसे जानें, इससे पहले कि आप पृष्ठ की सेवा शुरू कर सकें, इससे पहले आप 20 प्रश्नों को निष्पादित कर रहे हैं। यह पूरी तरह से प्रदर्शन को नष्ट कर देता है।

    कुछ चौखटे - और मैं यहां मुख्य रूप से NHibernate के बारे में सोच रहा हूं - इस बारे में अविश्वसनीय रूप से चतुर हैं और आपको फ्यूचर नामक कुछ का उपयोग करने की अनुमति देते हैं जो पूरे प्रश्नों को बैचते हैं और उन सभी को अंतिम समय पर एक बार में निष्पादित करने का प्रयास करते हैं। AFAIK, यदि आप Microsoft तकनीकों में से किसी के साथ ऐसा करना चाहते हैं, तो आप अपने दम पर हैं; आपको इसे अपने एप्लिकेशन लॉजिक में बनाना होगा।

  5. अनुक्रमण, विधेय और अनुमान

    कम से कम 50% देवों से मैं बात करता हूं और यहां तक ​​कि कुछ डीबीए को भी अनुक्रमणिका को कवर करने की अवधारणा से परेशानी होती है। वे सोचते हैं, "ठीक है, Customer.Nameकॉलम को अनुक्रमित किया गया है, इसलिए मैं नाम पर प्रत्येक लुकअप फास्ट होना चाहिए।" सिवाय इसके कि यह उस तरह से काम नहीं करता है जब तक कि Nameसूचकांक आपके द्वारा देखे जा रहे विशिष्ट कॉलम को कवर नहीं करता है । SQL सर्वर में, यह कथन INCLUDEमें किया गया CREATE INDEXहै।

    यदि आप SELECT *हर जगह भोलेपन का उपयोग करते हैं - और यह कमोबेश हर ओआरएम क्या करेगा जब तक आप स्पष्ट रूप से अन्यथा एक प्रक्षेपण का उपयोग करते हुए निर्दिष्ट नहीं करते हैं - तब डीबीएमएस बहुत अच्छी तरह से आपके अनुक्रमितों को पूरी तरह से अनदेखा करने का विकल्प चुन सकते हैं क्योंकि उनमें गैर-कवर किए गए कॉलम होते हैं। एक प्रक्षेपण का अर्थ है, उदाहरण के लिए, ऐसा करने के बजाय:

    from c in db.Customers where c.Name == "John Doe" select c
    

    आप इसके बजाय ऐसा करें:

    from c in db.Customers where c.Name == "John Doe"
    select new { c.Id, c.Name }
    

    और यह होगा, सबसे आधुनिक ORMs के लिए, हिदायत यह केवल जाने के लिए और क्वेरी करने के लिए Idऔर Nameकॉलम जो संभवतः सूचकांक के अंतर्गत आते हैं (लेकिन नहीं Email, LastActivityDate, या कोई अन्य स्तंभों तुम वहाँ में रहना हुआ)।

    अनुचित विधेय का उपयोग करके किसी भी अनुक्रमण लाभों को पूरी तरह से दूर करना भी बहुत आसान है। उदाहरण के लिए:

    from c in db.Customers where c.Name.Contains("Doe")
    

    ... लगभग हमारी पिछली क्वेरी के समान है, लेकिन वास्तव में इसका परिणाम पूर्ण तालिका या इंडेक्स स्कैन में होगा क्योंकि यह अनुवाद करता है LIKE '%Doe%'। इसी तरह, एक और क्वेरी जो संदिग्ध रूप से सरल लगती है:

    from c in db.Customers where (maxDate == null) || (c.BirthDate >= maxDate)
    

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

    from c in db.Customers where c.BirthDate >= (maxDate ?? DateTime.MinValue)
    

    ... अब DB इंजन जानता है कि इसे कैसे परिमाणित करना है और एक सूचकांक की तलाश है। क्वेरी अभिव्यक्ति में एक मामूली, प्रतीत होता है नगण्य परिवर्तन प्रदर्शन को काफी प्रभावित कर सकता है।

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

    मूल रूप से यह सब इस तथ्य पर उतरता है कि आपको वास्तव में उत्पन्न एसक्यूएल और निष्पादन योजनाओं दोनों पर कड़ी नजर रखनी होगी और यदि आप उन परिणामों को प्राप्त नहीं कर रहे हैं जिनकी आपको उम्मीद है, तो डरें नहीं। ORM लेयर को एक बार और SQL को हैंड-कोड करें। यह किसी भी ORM के लिए जाता है , न कि केवल EF के लिए।

  6. लेन-देन और ताला

    क्या आपको मिलीसेकंड तक मौजूद डेटा को प्रदर्शित करने की आवश्यकता है? शायद - यह निर्भर करता है - लेकिन शायद नहीं। अफसोस की बात है कि, एंटिटी फ्रेमवर्क आपको नहीं देता हैnolock , आप केवल लेनदेन स्तर (तालिका स्तर नहीं) READ UNCOMMITTEDपर उपयोग कर सकते हैं । वास्तव में कोई भी ORM इस बारे में विशेष रूप से विश्वसनीय नहीं है; यदि आप गंदे रीडिंग करना चाहते हैं, तो आपको एसक्यूएल स्तर तक गिरना होगा और एड-हॉक क्वेरी या स्टोर की गई प्रक्रियाओं को लिखना होगा। तो क्या यह उबलता है, फिर से, आपके लिए फ्रेमवर्क के भीतर यह करना कितना आसान है।

    एंटिटी फ्रेमवर्क ने इस संबंध में एक लंबा सफर तय किया है - ईएफ का संस्करण 1 (.NET 3.5 में) ईश्वर-विस्मयकारी था, जिससे "संस्थाओं" अमूर्त के माध्यम से तोड़ना अविश्वसनीय रूप से कठिन हो गया, लेकिन अब आपके पास ExecuteStoreQuery और अनुवाद है , इसलिए यह वास्तव में है इतना भी बेकार नहीं। इन लोगों से दोस्ती करें क्योंकि आप इनका भरपूर इस्तेमाल करेंगे।

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

    ध्यान दें कि एक UOW लंबे समय तक चलने वाले लेनदेन के अनुरूप नहीं है । UOW अभी भी ORM की आशावादी संगामिति सुविधाओं का उपयोग करता है और स्मृति में सभी परिवर्तनों को ट्रैक करता है । अंतिम प्रतिबद्ध होने तक एक भी DML कथन उत्सर्जित नहीं होता है। इससे लेनदेन का समय कम से कम रहता है। यदि आप कच्चे SQL का उपयोग करके अपना एप्लिकेशन बनाते हैं, तो इस स्थगित व्यवहार को प्राप्त करना काफी मुश्किल है।

    विशेष रूप से ईएफ के लिए इसका क्या मतलब है: अपनी इकाइयों को जितना संभव हो सके उतना कठिन बनाएं और जब तक आपको बिल्कुल ज़रूरत न हो, तब तक उन्हें प्रतिबद्ध न करें। ऐसा करें और आप यादृच्छिक समय पर व्यक्तिगत ADO.NET कमांड का उपयोग करने की तुलना में बहुत कम लॉक विवाद के साथ समाप्त करेंगे।

निष्कर्ष के तौर पर:

उच्च ट्रैफ़िक / उच्च-प्रदर्शन अनुप्रयोगों के लिए EF पूरी तरह से ठीक है, ठीक उसी तरह जैसे हर दूसरा फ्रेमवर्क उच्च-ट्रैफ़िक / उच्च-प्रदर्शन अनुप्रयोगों के लिए ठीक है। क्या मायने रखता है कि आप इसका उपयोग कैसे करते हैं। यहां सबसे लोकप्रिय फ्रेमवर्क की त्वरित तुलना है और वे प्रदर्शन के संदर्भ में क्या विशेषताएं प्रदान करते हैं (किंवदंती: एन = समर्थित नहीं, पी = आंशिक, वाई = हाँ / समर्थित):

                                | L2S | EF1 | EF4 | NH3 | ADO
                                +-----+-----+-----+-----+-----
Lazy Loading (entities)         |  N  |  N  |  N  |  Y  |  N
Lazy Loading (relationships)    |  Y  |  Y  |  Y  |  Y  |  N
Eager Loading (global)          |  N  |  N  |  N  |  Y  |  N
Eager Loading (per-session)     |  Y  |  N  |  N  |  Y  |  N
Eager Loading (per-query)       |  N  |  Y  |  Y  |  Y  |  Y
Level 1 (Identity) Cache        |  Y  |  Y  |  Y  |  Y  |  N
Level 2 (Query) Cache           |  N  |  N  |  P  |  Y  |  N
Compiled Queries                |  Y  |  P  |  Y  |  N  | N/A
Multi-Queries                   |  N  |  N  |  N  |  Y  |  Y
Multiple Result Sets            |  Y  |  N  |  P  |  Y  |  Y
Futures                         |  N  |  N  |  N  |  Y  |  N
Explicit Locking (per-table)    |  N  |  N  |  N  |  P  |  Y
Transaction Isolation Level     |  Y  |  Y  |  Y  |  Y  |  Y
Ad-Hoc Queries                  |  Y  |  P  |  Y  |  Y  |  Y
Stored Procedures               |  Y  |  P  |  Y  |  Y  |  Y
Unit of Work                    |  Y  |  Y  |  Y  |  Y  |  N

जैसा कि आप देख सकते हैं, EF4 (वर्तमान संस्करण) बहुत बुरी तरह से किराया नहीं करता है, लेकिन संभवतः यह सबसे अच्छा नहीं है यदि प्रदर्शन आपकी प्राथमिक चिंता है। NHibernate इस क्षेत्र में बहुत अधिक परिपक्व है और यहां तक ​​कि Linq to SQL कुछ प्रदर्शन-बढ़ाने वाली सुविधाएँ प्रदान करता है जो EF अभी भी नहीं करता है। रॉ ADO.NET अक्सर बहुत विशिष्ट डेटा-एक्सेस परिदृश्यों के लिए तेज़ होने वाला है, लेकिन, जब आप सभी टुकड़ों को एक साथ रखते हैं, तो यह वास्तव में बहुत सारे महत्वपूर्ण लाभों की पेशकश नहीं करता है जो आपको विभिन्न रूपरेखाओं से मिलते हैं।

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


38
क्या कमाल और व्यापक जवाब!

2
+1 (अधिक अगर मैं कर सकता था) - सबसे अच्छा जवाबों में से एक जो मैंने यहां थोड़ी देर में देखा है और मैंने एक चीज या दो सीखी - इसे साझा करने के लिए धन्यवाद!
ब्रोकनग्लास

1
यह बहुत अच्छा जवाब है यहां तक ​​कि मैं उल्लेख की गई सभी चीजों से सहमत नहीं हूं। ओआरएम की तुलना करने वाली तालिका हमेशा सही नहीं होती है। आलसी लोडिंग इकाइयाँ क्या है? क्या आपका मतलब है आलसी लोडेड कॉलम? यह L2S में समर्थित है। आपको क्या लगता है कि NH संकलित प्रश्नों का समर्थन नहीं करता है? मुझे लगता है कि HQL प्रश्नों का नाम पूर्व संकलित किया जा सकता है। EF4 में कई परिणाम सेट के लिए कोई समर्थन नहीं है।
लादिस्लाव मृका

11
मुझे अयोग्य "ईएफ उच्च यातायात / उच्च प्रदर्शन अनुप्रयोगों" के लिए पूरी तरह से असहमत है, इस कथन के साथ, हमने बार-बार देखा है कि यह मामला नहीं है। दी, हो सकता है कि हम क्या "उच्च प्रदर्शन" का अर्थ है पर असहमत हैं, लेकिन उदाहरण के लिए 500ms के लिए नीचे वेब पृष्ठों को बेहतर बनाने और 400 मि.से कि + ढांचे के अंदर बेवजह खर्च होने (और केवल 10ms वास्तव में मार एसक्यूएल) कुछ स्थितियों के लिए "ठीक" नहीं है, यह हमारी देव टीम के लिए सर्वथा अस्वीकार्य है।
निक क्रैकर

1
ईएफ में वायदा के बारे में सरल नोट। वे आधिकारिक तौर पर एमएस ईएफ टीम द्वारा प्रदान नहीं किए जाते हैं, लेकिन थर्ड पार्टी प्रोजेक्ट्स के जरिए हासिल किए जा सकते हैं जो फ्यूचर <> एक्सटेंशन को IQueryable <> में परिभाषित करते हैं। उदाहरण के लिए EntityFramework.Extended द्वारा लोरसॉफ्ट, NuGet में उपलब्ध है। भविष्य के उपयोग से एकल बैच में दर्जनों गैर-निर्भर प्रश्नों (सभी प्रश्नों को समानांतर में निष्पादित किया जा सकता है, किसी को भी पिछले एक के परिणाम की आवश्यकता नहीं होती है) के उत्पादन में मेरे व्यक्तिगत परीक्षण 10x तक का प्रदर्शन प्राप्त करते हैं। इसके अलावा AsNoTracking () प्रदर्शन को बेहतर बनाता है जब सिर्फ बहुत सारे रिकॉर्ड पढ़ते हैं, बाद में कोई अपडेट नहीं होता है।
डेविड ओलिवान उबिय्टो

38

संपादित करें: @ शानदार उत्तर के आधार पर मैं EF के साथ कुछ लक्ष्यीकरण प्रदर्शन जोड़ रहा हूं। उन नए बिंदुओं को उपसर्ग द्वारा संपादित किया गया है।


उच्च ट्रैफ़िक वेबसाइटों में प्रदर्शन में सबसे बड़ा सुधार कैशिंग (= किसी वेब सर्वर प्रोसेसिंग या डेटाबेस क्वेरी से बचने के लिए सबसे पहले) द्वारा किया जाता है, उसके बाद एसिंक्रोनस प्रोसेसिंग द्वारा थ्रेड ब्लॉकिंग से बचने के लिए डेटाबेस क्वेरीज़ का प्रदर्शन किया जाता है।

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

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

यदि आप EF से सर्वश्रेष्ठ प्रदर्शन प्राप्त करना चाहते हैं, तो आपको सबसे अधिक संभव होगा:

  • बहुत सावधानी से SQL प्रोफाइलर के साथ अपने डेटा एक्सेस को संशोधित करें और अपने LINQ प्रश्नों की समीक्षा करें यदि वे Linq-to-संस्थाओं के बजाय Linq-to-संस्थाओं का सही उपयोग करते हैं
  • बहुत सावधानी से उन्नत EF अनुकूलन सुविधाओं का उपयोग करें MergeOption.NoTracking
  • कुछ मामलों में ESQL का उपयोग करें
  • पूर्व-संकलित क्वेरी जो अक्सर निष्पादित की जाती हैं
  • कुछ प्रश्नों के लिए फीचर की तरह "सेकंड लेवल कैश" पाने के लिए ईएफ कैशिंग रैपर का लाभ उठाने के बारे में सोचें
  • अक्सर उपयोग किए गए अनुमानों या एकत्रीकरण के लिए कुछ परिदृश्यों में SQL विचारों या कस्टम मैप्ड SQL क्वेरीज़ (EDMX फ़ाइल के मैनुअल मेंटेनेंस की आवश्यकता होती है) का उपयोग करें, जिसमें प्रदर्शन सुधार की आवश्यकता होती है
  • कुछ प्रश्नों के लिए देशी SQL और संग्रहीत कार्यविधियों का उपयोग करें जो Linq या ESQL में परिभाषित होने पर पर्याप्त प्रदर्शन प्रदान नहीं करते हैं
  • संपादित करें: सावधानीपूर्वक प्रश्नों का उपयोग करें - प्रत्येक क्वेरी डेटाबेस के लिए अलग-अलग राउंडट्रिप बनाती है। EFv4 में कोई क्वेरी बैचिंग नहीं है क्योंकि यह निष्पादित डेटाबेस कमांड के अनुसार कई परिणाम सेट का उपयोग करने में सक्षम नहीं है। EFv4.5 मैप की गई कार्यविधियों के लिए कई परिणाम सेटों का समर्थन करेगा।
  • संपादित करें: डेटा संशोधनों के साथ सावधानीपूर्वक काम करेंईएफ के पास फिर से कमांड बैचिंग का अभाव है । तो ADO.NET में आप एक SqlCommandसे अधिक इन्सर्ट, अपडेट या डिलीट वाले सिंगल का उपयोग कर सकते हैं लेकिन EF के साथ हर ऐसे कमांड को डेटाबेस के लिए अलग-अलग राउंडट्रिप में निष्पादित किया जाएगा।
  • संपादित करें: सावधानी से पहचान मानचित्र / पहचान कैश के साथ काम करें। पहले कैश को क्वेरी करने के लिए EF में विशेष विधि ( GetByKeyObjectContext API या FindDbContext API में) है। यदि आप Linq-to-संस्थाओं या ESQL का उपयोग करते हैं तो यह डेटाबेस में राउंडट्रिप बनाएगा और उसके बाद यह कैश से मौजूदा उदाहरण लौटाएगा।
  • संपादित करें: सावधानीपूर्वक उत्सुक लोडिंग का उपयोग करें । यह हमेशा जीत-जीत समाधान नहीं है क्योंकि यह एक विशाल डेटासेट का उत्पादन करता है । जैसा कि आप देख सकते हैं कि यह बहुत सी अतिरिक्त जटिलता है और यह संपूर्ण बिंदु है। ORM मैपिंग और मटीरियलिज़्म को सरल बनाता है लेकिन प्रदर्शन से निपटने पर यह बहुत अधिक जटिल हो जाएगा और आपको ट्रेड-ऑफ करना होगा।

मुझे यकीन नहीं है कि एसओ अभी भी L2S का उपयोग कर रहा है। उन्होंने नया खुला स्रोत ओआरएम विकसित किया जिसे डैपर कहा जाता है और मुझे लगता है कि इस विकास के पीछे मुख्य बिंदु प्रदर्शन बढ़ रहा था।


लदिस्लाव, यह वास्तव में उपयोगी उत्तर है। यह पहली बार है जब मैंने डैपर के बारे में सुना (और फलस्वरूप पेटाकोको, बड़े पैमाने पर खोजा गया) - और यह एक दिलचस्प विचार जैसा दिखता है।

1
SO अब SQL और Dapper के लिए LINQ के मिश्रण का उपयोग करने लगता है: samsaffron.com/archive/2011/03/30/… उद्धरण: "हम एक विशेष समस्या के लिए अपने नए ORM [Dapper] का उपयोग कर रहे हैं: व्यापार के ऑब्जेक्ट के लिए पैरामीटर किए गए SQL को मैप करना हम इसे पूर्ण विकसित ORM के रूप में उपयोग नहीं कर रहे हैं। यह रिश्तों और अन्य घंटियाँ और सीटी नहीं करता है। यह हमें LINQ-2-SQL का उपयोग करना जारी रखने की अनुमति देता है जहां प्रदर्शन कोई फर्क नहीं पड़ता है और हमारे सभी इनलाइन SQL को हमारे मस्टर का उपयोग करने के लिए पोर्ट करता है। चूंकि यह तेज और अधिक लचीला है। "

5
@ सलूमा कुआं, जो महीनों पहले का एक बयान है, सामान्य तौर पर एसओ पर सभी नए काम डापर में किए जाते हैं, उदाहरण के लिए मैंने आज जो नई तालिका जोड़ी है, वह डीबीएमएल फ़ाइल में भी नहीं है।
सैम सैफ्रन

1
@ एसएएम: क्या एसओ पर वर्तमान डेटा एक्सेस रणनीति के बारे में एक नया ब्लॉग पोस्ट है? बहुत दिलचस्प होगा ! क्या इस बीच डापर को बढ़ाया गया है? मेरी समझ यह थी कि डैपर एक पूर्ण ORM नहीं है, रिश्तों का कोई समर्थन नहीं है - और अद्यतन, आवेषण,
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.