अद्यतन 3: इस घोषणा के अनुसार , यह EF6 अल्फा 2 में EF टीम द्वारा संबोधित किया गया है।
अद्यतन 2: मैंने इस समस्या को ठीक करने के लिए एक सुझाव दिया है। इसे वोट करने के लिए, यहां जाएं ।
एक बहुत ही सरल तालिका के साथ एक SQL डेटाबेस पर विचार करें।
CREATE TABLE Main (Id INT PRIMARY KEY)
मैं 10,000 रिकॉर्ड के साथ तालिका को आबाद करता हूं।
WITH Numbers AS
(
SELECT 1 AS Id
UNION ALL
SELECT Id + 1 AS Id FROM Numbers WHERE Id <= 10000
)
INSERT Main (Id)
SELECT Id FROM Numbers
OPTION (MAXRECURSION 0)
मैं तालिका के लिए एक EF मॉडल बनाता हूं और LINQPad में निम्नलिखित क्वेरी चलाता हूं (मैं "C # कथन" मोड का उपयोग कर रहा हूं ताकि LINQPad स्वचालित रूप से एक डंप नहीं बना सके)।
var rows =
Main
.ToArray();
निष्पादन का समय ~ 0.07 सेकंड है। अब मैं Contains ऑपरेटर जोड़ता हूं और क्वेरी को फिर से चलाता हूं।
var ids = Main.Select(a => a.Id).ToArray();
var rows =
Main
.Where (a => ids.Contains(a.Id))
.ToArray();
इस मामले का निष्पादन समय 20.14 सेकंड (288 गुना धीमा) है!
पहले मुझे संदेह था कि क्वेरी के लिए उत्सर्जित T-SQL निष्पादन में अधिक समय ले रहा है, इसलिए मैंने LINQPad के SQL फलक से SQL सर्वर प्रबंधन स्टूडियो में इसे काटने और चिपकाने की कोशिश की।
SET NOCOUNT ON
SET STATISTICS TIME ON
SELECT
[Extent1].[Id] AS [Id]
FROM [dbo].[Primary] AS [Extent1]
WHERE [Extent1].[Id] IN (1,2,3,4,5,6,7,8,...
और परिणाम था
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 88 ms.
अगला मुझे शक था कि लिनक्यूपैड समस्या पैदा कर रहा है, लेकिन प्रदर्शन वही है कि मैं इसे लिनक्यूपैड में चलाऊं या कंसोल एप्लिकेशन में।
तो, ऐसा प्रतीत होता है कि समस्या कहीं न कहीं एंटिटी फ्रेमवर्क के भीतर है।
क्या मुझसे यहां कुछ गलत हो रहा है? यह मेरे कोड का एक समय-महत्वपूर्ण हिस्सा है, इसलिए प्रदर्शन को गति देने के लिए मैं कुछ कर सकता हूं?
मैं Entity Framework 4.1 और Sql Server 2008 R2 का उपयोग कर रहा हूं।
अद्यतन 1:
नीचे चर्चा में कुछ सवाल थे कि क्या ईएफ प्रारंभिक क्वेरी का निर्माण करते समय देरी हो रही थी या जब यह डेटा वापस प्राप्त कर रहा था तो यह पार्स कर रहा था। इसका परीक्षण करने के लिए मैंने निम्नलिखित कोड चलाया,
var ids = Main.Select(a => a.Id).ToArray();
var rows =
(ObjectQuery<MainRow>)
Main
.Where (a => ids.Contains(a.Id));
var sql = rows.ToTraceString();
जो EF को डेटाबेस के विरुद्ध निष्पादन किए बिना क्वेरी उत्पन्न करने के लिए मजबूर करता है। इसका परिणाम यह हुआ कि इस कोड को चलाने के लिए ~ 20 सेकंड की आवश्यकता होती है, इसलिए ऐसा प्रतीत होता है कि प्रारंभिक क्वेरी के निर्माण में लगभग सभी समय लिया जाता है।
बचाव के लिए CompiledQuery तो? इतनी जल्दी नहीं ... CompiledQuery को मौलिक प्रकार (इंट, स्ट्रिंग, फ्लोट, और इसी तरह) होने के लिए पैरामीटर में क्वेरी की आवश्यकता होती है। यह सरणियों या IEnumerable को स्वीकार नहीं करेगा, इसलिए मैं इसे Ids की सूची के लिए उपयोग नहीं कर सकता।
var qry = Main.Where (a => ids.Contains(a.Id)); var rows = qry.ToArray();
यह देखने की कोशिश की है कि क्वेरी के किस भाग में समय लग रहा है?