2012-09-14 17 views
9

मैं इकाई की रूपरेखा का उपयोग कर रहा मौजूद है और मैं जाँच करने के लिए करता है, तो नाम = "xyz" के साथ एक उत्पाद मौजूद है ...संस्थाओं के लिए LINQ - कोई वी.एस. पहले वी.एस.

मुझे लगता है कि मैं किसी भी (उपयोग कर सकते हैं की जरूरत है), मौजूद है () या पहले()।

इस तरह की स्थिति के लिए कौन सा सबसे अच्छा विकल्प है? किसके पास सबसे अच्छा प्रदर्शन है?

धन्यवाद,

मिगुएल

उत्तर

15

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

कम से कम आपने इसके बारे में नहीं पूछा था। जहां (x => x.Count()> 0) जिसके लिए पूरे मैच सेट का मूल्यांकन किया जाना चाहिए और इससे पहले कि आप यह निर्धारित कर सकें कि आपके पास एक रिकॉर्ड है। कोई शॉर्ट-सर्किट अनुरोध और काफी तेजी से हो सकता है।

+3

+1। स्पष्टीकरण के लिए: पूरे मिलान सेट को गिनती डेटाबेस स्तर पर की जाती है, इसलिए यह आपके एप्लिकेशन में ऑब्जेक्ट्स नहीं ला रहा है। अभी भी 'कोई() 'सरल है, और यह' कहीं भी (x => x.Count> 0) 'से बेहतर प्रदर्शन करेगा, इसलिए इसे प्राथमिकता दी जानी चाहिए। – StriplingWarrior

+0

@StriplingWarrior यह सच है कि गणना डीबी में की जाती है, लेकिन यह अभी भी गिनती से भी बदतर है, ईएफ की भयानक क्वेरी पीढ़ी के लिए धन्यवाद। मेरा जवाब देखें –

1

Any() और First()IEnumerable जो आप चीजों lazily के मूल्यांकन के लिए लचीलापन प्रदान करता है के साथ प्रयोग किया जाता है। हालांकि Exists() सूची की आवश्यकता है।

मुझे आशा है कि यह आपके लिए चीजों को साफ़ कर देगा और यह तय करने में आपकी सहायता करेगा कि किस का उपयोग करना है।

2

एक Any() बेहतर परिणाम देता है, क्योंकि यह एक EXISTS क्वेरी करने के लिए अनुवाद लगता होगा ... लेकिन एफई बहुत टूट गया है, पैदा करने के लिए इस (संपादित):

SELECT 
CASE WHEN (EXISTS (SELECT 
    1 AS [C1] 
    FROM [MyTable] AS [Extent1] 
    WHERE Condition 
)) THEN cast(1 as bit) WHEN (NOT EXISTS (SELECT 
    1 AS [C1] 
    FROM [MyTable] AS [Extent2] 
    WHERE Condition 
)) THEN cast(0 as bit) END AS [C1] 
FROM (SELECT 1 AS X) AS [SingleRowTable1] 

बजाय:

SELECT 
CASE WHEN (EXISTS (SELECT 
    1 AS [C1] 
    FROM [MyTable] AS [Extent1] 
    WHERE Condition 
)) THEN cast(1 as bit) 
    ELSE cast(0 as bit) END AS [C1] 
FROM (SELECT 1 AS X) AS [SingleRowTable1] 

... मूल रूप से क्वेरी लागत को दोगुना करना (सरल प्रश्नों के लिए; यह जटिल लोगों के लिए भी बदतर है)

मुझेका उपयोग मिला हैतेजी से बहुत तेज़ है (लागत ठीक तरह से लिखित EXISTS क्वेरी के समान है)

+1

एक दिलचस्प अवलोकन, लेकिन मुझे डर है कि यह जवाब संभावित रूप से भ्रामक शुरुआत के बिंदु पर चीजों को अधिक बढ़ा देता है। [मेरा जवाब देखें] (http://stackoverflow.com/a/12439909/120955)। – StriplingWarrior

22

ठीक है, मैं इस पर वजन नहीं ले रहा था, लेकिन डिएगो का जवाब पर्याप्त चीजों को जटिल करता है जो मुझे लगता है कि कुछ अतिरिक्त स्पष्टीकरण सुव्यवस्थित है।

ज्यादातर मामलों में, .Any() तेज होगा। यहां कुछ उदाहरण दिए गए हैं।

Workflows.Where(w => w.Activities.Any()) 
Workflows.Where(w => w.Activities.Any(a => a.Title == "xyz")) 

उपरोक्त दो उदाहरणों में, इकाई फ्रेमवर्क एक इष्टतम क्वेरी उत्पन्न करता है। .Any() कॉल एक अनुमान का हिस्सा है, और इकाई फ्रेमवर्क इस अच्छी तरह से संभालता है। हालांकि, हम परिणाम इस तरह सेट की .Any() भाग का परिणाम बनाने यदि:

Workflows.Select(w => w.Activities.Any(a => a.Title == "xyz")) 

... अचानक इकाई की रूपरेखा हालत के दो संस्करण बनाने का निर्णय लेती है, तो क्वेरी के रूप में ज्यादा के रूप में दो बार यह काम करता है वास्तव में करने की जरूरत है।हालांकि, निम्न क्वेरी किसी भी बेहतर नहीं है:

Workflows.Select(w => w.Activities.Count(a => a.Title == "xyz") > 0) 

ऊपर क्वेरी को देखते हुए, इकाई की रूपरेखा अभी भी हालत के दो संस्करणों का निर्माण करेगा प्लस यह भी एसक्यूएल सर्वर की आवश्यकता होगी एक वास्तविक गणना करने के लिए है, जो इसका मतलब है जैसे ही कोई आइटम पाता है, शॉर्ट-सर्किट में नहीं मिलता है।

लेकिन अगर आप इन दो प्रश्नों की तुलना कर रहे:

  1. Activities.Any(a => a.Title == "xyz")
  2. Activities.Count(a => a.Title == "xyz") > 0

... तेजी से हो जाएगा जो? निर्भर करता है।

पहली क्वेरी एक अक्षम डबल-कंडीशन क्वेरी उत्पन्न करती है, जिसका अर्थ है कि इसे दो गुना तक लेना होगा।

दूसरी क्वेरी डेटाबेस में प्रत्येक आइटम को शॉर्ट-सर्किटिंग के बिना जांचने के लिए मजबूर करती है, जिसका अर्थ है कि इसे N गुना अधिक समय तक लेना पड़ सकता है, इस पर निर्भर करता है कि मैच खोजने से पहले कितने आइटमों का मूल्यांकन किया जाना चाहिए । की मेज मान लेते हैं 10,000 आइटम नहीं है:

  • तालिका में कोई आइटम हालत मेल खाता है, इस प्रश्न के पहले प्रश्न के रूप में लगभग आधा समय ले जाएगा।
  • यदि तालिका में पहला आइटम स्थिति से मेल खाता है, तो इस क्वेरी में पहली क्वेरी की तुलना में लगभग 5,000 गुना अधिक लगेगा।
  • यदि तालिका में एक आइटम एक मैच है, तो यह क्वेरी पहली क्वेरी की तुलना में औसत 2,500 गुना अधिक ले जाएगी।
  • यदि क्वेरी Title और कुंजी कॉलम पर एक सूचकांक का लाभ उठाने में सक्षम है, तो यह क्वेरी पहली क्वेरी के रूप में लगभग आधे समय ले जाएगी।
तो सारांश में

, यदि आप:

  1. का उपयोग इकाई की रूपरेखा 4 (नए संस्करण क्वेरी संरचना में सुधार हो सकता के बाद से) इकाई की रूपरेखा 6.1 या उससे पहले (6.1.1 has a fix to improve the query के बाद से), और
  2. तालिका के खिलाफ सीधे पूछताछ (जैसा कि उप-क्वेरी करने के विपरीत है), और
  3. परिणाम का उपयोग सीधे (जैसा कि भविष्यवाणी का हिस्सा है) का उपयोग करना, और
  4. ईट उसे:
    1. आप अच्छा अनुक्रमित तालिका आप जानना चाहते हैं पर स्थापित है, या
    2. आप आइटम समय के बहुमत पाया जा करने के लिए नहीं की उम्मीद

तो आप .Any() उम्मीद कर सकते हैं .Count() जितना अधिक समय तक लेना। उदाहरण के लिए, एक प्रश्न 50 के बजाय 100 मिलीसेकंड ले सकता है। या 5 के बजाय 10।

किसी भी अन्य परिस्थिति.Any() में कम से कम तेजी से रूप होना चाहिए, और परिमाण के संभवतः आदेश तेजी से.Count() से।

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

+0

यदि आप किसी भी() बग (?) के आसपास काम करने की कोशिश कर रहे हैं, इसे 'गणना()> 0' में परिवर्तित करने के बजाय, मैं' FirstOrDefault()! = Null' का उपयोग करूंगा। – Mormegil

+0

@ मॉर्मेलिल: एक दिलचस्प विचार। लेकिन मैंने इसका परीक्षण किया, और यह दो बाहरी-लागू चयन वक्तव्यों के साथ एक पागल सवाल भी बनाता है। तो यह वास्तव में समस्या को हल नहीं करता है, और यह कोड (मेरी राय में) थोड़ा कम स्पष्ट बनाता है। – StriplingWarrior

+3

+1 "जब तक आपने यह निर्धारित नहीं किया है कि यह वास्तव में आपके उत्पाद में खराब प्रदर्शन का स्रोत है, तो आपको समझना आसान है कि आपको क्या समझना आसान है।" टिप्पणी –

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