एंटिटी फ्रेमवर्क क्वेरी धीमी है, लेकिन SqlQuery में समान एसक्यूएल तेज है


93

मैं एंटिटी फ्रेमवर्क कोड-प्रथम के साथ .NET फ्रेमवर्क संस्करण का उपयोग करते हुए एक बहुत ही सरल क्वेरी से संबंधित कुछ अजीब अजीब देख रहा हूं। LINQ2Entities क्वेरी इस तरह दिखता है:

 context.MyTables.Where(m => m.SomeStringProp == stringVar);

इसे निष्पादित करने में 3000 मिलीसेकंड से अधिक का समय लगता है। उत्पन्न SQL बहुत सरल दिखता है:

 SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
 ...
 FROM [MyTable] as [Extent1]
 WHERE [Extent1].[SomeStringProp] = '1234567890'

प्रबंधन स्टूडियो के माध्यम से चलने पर यह क्वेरी लगभग तुरंत चलती है। जब मैं SqlQuery फ़ंक्शन का उपयोग करने के लिए C # कोड बदलता हूं, तो यह 5-10 मिलीसेकंड में चलता है:

 context.MyTables.SqlQuery("SELECT [Extent1].[ID] ... WHERE [Extent1].[SomeStringProp] = @param", stringVar);

तो, एक ही एसक्यूएल, परिणामी इकाइयां दोनों मामलों में परिवर्तन-ट्रैक हैं, लेकिन दोनों के बीच जंगली पूर्ण अंतर है। क्या देता है?


2
मुझे उम्मीद है कि आप आरंभीकरण में देरी देख रहे हैं - शायद संकलन देखें। MSDN देखें:Performance Considerations for Entity Framework 5
निकोलस बटलर

मैंने पूर्व-उत्पादक दृश्य आज़माए हैं, और यह मदद करने के लिए प्रतीत नहीं होता है। इसके अलावा, इनिशियलाइज़ेशन सामान को नियंत्रित करने के लिए धीमी गति से पहले एक और ईएफ क्वेरी को चलाया। नई क्वेरी जल्दी से चली गई, धीमी गति से चलने वाला एक धीरे-धीरे, भले ही संदर्भ वार्म-अप पहली क्वेरी के दौरान हुआ हो।
ब्रायन सुलिवन

1
@marc_s - नहीं, SqlQuery पूरी तरह से भौतिकीकृत और परिवर्तन-ट्रैक इकाई उदाहरण लौटाएगा। देखें msdn.microsoft.com/en-us/library/...
ब्रायन सुलिवन

क्या आपकी EF क्वेरी के लिए उत्पन्न SQL वास्तव में पैरामीटर मान को कम कर रहा है, या एक पैरामीटर का उपयोग कर रहा है? यह एक व्यक्तिगत क्वेरी के लिए क्वेरी गति को प्रभावित नहीं करना चाहिए, लेकिन समय के साथ सर्वर में क्वेरीप्लेन ब्लोट का कारण बन सकता है।
जिम वोलेई

क्या आपने एक ही क्वेरी को दो बार / कई बार चलाने की कोशिश की है? दूसरी बार चलने में कितना समय लगा? क्या आपने .NET फ्रेमवर्क 4.5 पर यह कोशिश की है - .NET फ्रेमवर्क 4.5 में कुछ EF संबंधित पूर्ण सुधार हैं जो मदद कर सकते हैं।
पावेल

जवाबों:


96

मिल गया। यह पता चला है कि यह SQL डेटा प्रकारों का एक मुद्दा है। SomeStringPropडेटाबेस में स्तंभ एक varchar था, लेकिन एफई मानता है कि नेट स्ट्रिंग प्रकार nvarchars हैं। डीबी की तुलना करने के लिए क्वेरी के दौरान परिणामी अनुवाद प्रक्रिया में एक लंबा समय लगता है। मुझे लगता है कि EF प्रो मुझे यहां थोड़ा भटका रहा था, जो क्वेरी के चलने का अधिक सटीक प्रतिनिधित्व निम्न होगा:

 SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
 ...
 FROM [MyTable] as [Extent1]
 WHERE [Extent1].[SomeStringProp] = N'1234567890'

इसलिए परिणामी फिक्स कोड-पहले मॉडल को एनोटेट करना है, जो सही एसक्यूएल डेटा प्रकार को दर्शाता है:

public class MyTable
{
    ...

    [Column(TypeName="varchar")]
    public string SomeStringProp { get; set; }

    ...
}

1
अच्छी छानबीन की। आपकी क्वेरी "निहित रूपांतरण" से पीड़ित थी, जैसा कि यहाँ बताया गया है: brentozar.com/archive/2012/07/…
Jaime

मुझे डिबगिंग के कुछ घंटे बचाया। ठीक यही समस्या थी।
कोडी

1
मेरे मामले में, मैं एक विरासत डेटाबेस के साथ ईडीएमएक्स का उपयोग कर रहा हूं, जो varcharसब कुछ के लिए उपयोग करता है, और वास्तव में यह समस्या थी। मुझे आश्चर्य है कि अगर मैं सब कुछ स्ट्रिंग कॉलम के लिए varchar पर विचार करने के लिए एक EDMX बना सकता हूं।
एलिसन

1
महान खोज आदमी। लेकिन @Jaime डेटाबेस के लिए हमें क्या करना चाहिए क्योंकि सब कुछ (जैसे db मॉडल पर डेटा एनोटेशन) डेटाबेस से EF मॉडल को अपडेट करने के बाद मिटा देता है।
नौमान खान

थोड़ी देर के लिए इसे अपने होम पेज के रूप में सेट करना ताकि मैं फिर से थोड़ी देर के लिए इस तरह के शानदार जवाब पाने की उत्तेजना को दूर कर सकूं। धन्यवाद!!!
ओजिसबाड

43

EF में किए गए मेरे प्रश्नों को धीमा करने का कारण अशक्त स्केलरों के साथ अशक्त स्केलर की तुलना नहीं करना था:

long? userId = 10; // nullable scalar

db.Table<Document>().Where(x => x.User.Id == userId).ToList() // or userId.Value
                                ^^^^^^^^^    ^^^^^^
                                Type: long   Type: long?

उस क्वेरी में 35 सेकंड लगे। लेकिन इस तरह एक छोटे से refactoring:

long? userId = 10;
long userIdValue = userId.Value; // I've done that only for the presentation pursposes

db.Table<Document>().Where(x => x.User.Id == userIdValue).ToList()
                                ^^^^^^^^^    ^^^^^^^^^^^
                                Type: long   Type: long

अविश्वसनीय परिणाम देता है। इसे पूरा करने में केवल 50ms का समय लगा। यह संभव है कि यह ईएफ में एक बग है।


13
यह बहुत अजीब है
डैनियल Cardenas

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

क्या इस बग की रिपोर्ट की गई है? यह अभी भी नवीनतम संस्करण 6.2.0
डिर्क बोअर

2
यही मुद्दा ईएफ कोर में भी है। इसे खोजने के लिए धन्यवाद!
यनिकवि

एक अन्य सुझाव LINQ अभिव्यक्ति में डालने से पहले चर को संसाधित करना है। अन्यथा उत्पन्न वर्ग बहुत लंबा और धीमा हो जाएगा। मैंने महसूस किया कि ट्राइक () और टोलॉवर () लाइनक्यू अभिव्यक्ति के अंदर है जो मुझे परेशान करता है।
समिहि

9

यदि आप धाराप्रवाह मानचित्रण का उपयोग कर रहे हैं, तो आप IsUnicode(false)समान प्रभाव प्राप्त करने के लिए कॉन्फ़िगरेशन के भाग के रूप में उपयोग कर सकते हैं -

http://msdn.microsoft.com/en-us/data/jj591617.aspx#1.9

http://msdn.microsoft.com/en-us/library/gg696416%28v=vs.103%29.aspx


4

मुझे एक ही समस्या थी (क्वेरी SQL प्रबंधक से निष्पादित होने पर तेज़ है) लेकिन जब EF से निष्पादित किया जाता है तो समय समाप्त हो जाता है।

यह बताता है कि इकाई (जो दृश्य से बनाई गई थी) में गलत इकाई कुंजी थी। इसलिए इकाई में समान कुंजियों के साथ डुप्लिकेट पंक्तियाँ थीं, और मुझे लगता है कि इसे पृष्ठभूमि पर समूहीकरण करना था।


3

मैं भी एक जटिल ef क्वेरी के साथ इस पार आया था। मेरे लिए एक फिक्स जिसने उप सेकंड एसक्यूएल क्वेरी के लिए 6 सेकंड की एफई क्वेरी को कम कर दिया था, यह आलसी लोडिंग को बंद करना था।

इस सेटिंग (ef 6) को खोजने के लिए .edmx फाइल पर जाएं और गुण -> कोड जनरेशन -> Lazy Loading Enabled में देखें। असत्य पर सेट करें।

मेरे लिए प्रदर्शन में व्यापक सुधार।


4
यह अच्छा है, लेकिन पोस्टर के सवाल से कोई लेना-देना नहीं है।
Jace Rhea

2

मुझे भी यह समस्या थी। यह पता चला है कि मेरे मामले में अपराधी SQL-Server था पैरामीटर सूँघ रहा था

पैरामीटर सूँघने के कारण मेरी पहली समस्या वास्तव में यह थी कि प्रबंधन स्टूडियो में "अलग तरीके से अलग-अलग निष्पादन समय" पर "सेट एरीथबॉर्ट ऑफ" या "सेट एरीथबॉर्ट" के साथ क्वेरी चल रही थी। इसका कारण यह है कि ADO.NET डिफ़ॉल्ट रूप से "सेट arithabort बंद" और प्रबंधन स्टूडियो को "सेट arithabort" पर डिफॉल्ट करता है। क्वेरी प्लान कैश इस पैरामीटर के आधार पर विभिन्न योजनाएं रखता है।

मैंने क्वेरी के लिए क्वेरी प्लान कैशिंग को अक्षम कर दिया है, इस समाधान के साथ आप यहां पा सकते हैं ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.