2011-05-01 8 views
6

इतिहासएसक्यूएल सीई के साथ LINQ आवेषण को कैसे गति दें?

मैं "रिकॉर्ड" (3500), जो मैं एक्सएमएल को बचाने के लिए और कार्यक्रम के बाहर निकलने पर सेक की एक सूची है। के बाद से:

  • अभिलेखों की संख्या बढ़ जाती है
  • केवल लगभग 50 रिकॉर्ड बाहर निकलने पर अद्यतन करने की आवश्यकता
  • की बचत के बारे में 3 सेकंड

मैं एक और समाधान की जरूरत लेता है - एम्बेडेड डेटाबेस। मैं एसक्यूएल सीई चुना है क्योंकि यह बिना किसी समस्या के वी.एस. के साथ काम करता है और लाइसेंस (मैं इसे Firebird, की तुलना में SQLite, EffiProz, db4o और BerkeleyDB) मेरे लिए ठीक है।

डेटा

रिकॉर्ड संरचना: 11 क्षेत्रों, उनमें से 2 प्राथमिक कुंजी (nvarchar + बाइट) बनाते हैं। अन्य रिकॉर्ड बाइट्स, डेटाटाइम, डबल और इंट्स हैं।

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

LINQ दृष्टिकोण

मैं खाली डेटाबेस (फाइल) है, तो मैं (एक के बाद एक) एक पाश में 3500 आवेषण बनाते हैं। मैं यह भी जांच नहीं करता कि रिकॉर्ड पहले से मौजूद है या नहीं क्योंकि डीबी खाली है।

निष्पादन समय? 4 मिनट, 52 सेकंड्स। मैं बेहोश हो गया (आपको दिमाग: एक्सएमएल + संपीड़न = 3 सेकंड)।

एसक्यूएल सीई कच्चे दृष्टिकोण

मैं थोड़ा googled, और इस तरह के दावों के बावजूद यहां के रूप में: LINQ to SQL (CE) speed versus SqlCe यह बताते हुए एसक्यूएल सीई ही गलती मैं इसे एक कोशिश दे दी है।

वही पाश लेकिन इस बार आवेषण SqlCeResultSet (DirectTable मोड, देखें: Bulk Insert In SQL Server CE) और SqlCeUpdatableRecord के साथ किए जाते हैं।

परिणाम? क्या आप आराम से बैठते हैं? खैर ... 0.3 सेकंड (हाँ, दूसरे का अंश!)।

समस्या

LINQ बहुत पढ़ी जा सकती है, और कच्चे संचालन काफी विपरीत है। मैं एक मैपर लिख सकता हूं जो सभी कॉलम इंडेक्स को सार्थक नामों में अनुवाद करता है, लेकिन ऐसा लगता है कि पहिया को फिर से शुरू करना - सब कुछ पहले से ही किया जा चुका है ... LINQ।

तो शायद यह LINQ को चीजों को गति देने के लिए कहने का एक तरीका है? प्रश्न - यह कैसे करें?

कोड

LINQ

foreach (var entry in dict.Entries.Where(it => it.AlteredByLearning)) 
{ 
    PrimLibrary.Database.Progress record = null; 

     record = new PrimLibrary.Database.Progress(); 
     record.Text = entry.Text; 
     record.Direction = (byte)entry.dir; 
     db.Progress.InsertOnSubmit(record); 

    record.Status = (byte)entry.LastLearningInfo.status.Value; 
    // ... and so on 

    db.SubmitChanges(); 
} 

कच्चे संचालन

SqlCeCommand cmd = conn.CreateCommand();

cmd.CommandText = "प्रगति"; cmd.CommandType = System.Data.CommandType.TableDirect; SqlCeResultSet rs = cmd.ExecuteResultSet (परिणाम SetOptions.Updatable);

foreach (var entry in dict.Entries.Where(it => it.AlteredByLearning)) 
{ 
    SqlCeUpdatableRecord record = null; 

    record = rs.CreateRecord(); 

    int col = 0; 
    record.SetString(col++, entry.Text); 
    record.SetByte(col++,(byte)entry.dir); 
    record.SetByte(col++,(byte)entry.LastLearningInfo.status.Value); 
    // ... and so on 

    rs.Insert(record); 
} 
+0

क्या आप कुछ कोड उदाहरण दिखा सकते हैं? –

+0

@ केविन पुलिन, निश्चित रूप से, मैंने यह समझने के लिए आवश्यक भागों को जोड़ा कि मैं दोनों मामलों में कैसे सम्मिलित करता हूं। – greenoldman

+0

क्या आपने ['BinaryFormatter'] (http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatters.binary.binaryformatter.aspx) की कोशिश की है? – svick

उत्तर

8

प्रति लेनदेन अधिक काम करें।

करता है आम तौर पर बहुत महंगा संचालन एक ठेठ रिलेशनल डेटाबेस के लिए डेटाबेस के रूप में डिस्क flushes सुनिश्चित करने के लिए डेटा खो नहीं है (ACID guarantees और जो कुछ) इंतज़ार करना होगा रहे हैं। विशेष नियंत्रकों के बिना परंपरागत एचडीडी डिस्क आईओ इस प्रकार के ऑपरेशन में बहुत धीमी है: डेटा भौतिक डिस्क पर फ़्लश किया जाना चाहिए - शायद केवल 30-60 काम एक आईओ सिंक के साथ एक सेकंड हो सकता है!

SQLite FAQ देखें: INSERT is really slow - I can only do few dozen INSERTs per second। विभिन्न डेटाबेस इंजन को अनदेखा करते हुए, यह एक ही समस्या है।

आम तौर पर, LINQ2SQL SubmitChanges के अंदर एक नया अंतर्निहित लेनदेन बनाता है। इस अंतर्निहित लेन-देन से बचने के लिए/प्रतिबद्ध या तो (प्रतिबद्ध महंगा संचालन हैं):

  1. कॉल SubmitChanges कम (जैसे कि, एक बार के बाहर पाश) या;

  2. एक स्पष्ट लेनदेन क्षेत्र स्थापित करें (TransactionScope देखें)। एक बड़ा लेन-देन संदर्भ का उपयोग करने का

ही एक उदाहरण है:

using (var ts = new TransactionScope()) { 
    // LINQ2SQL will automatically enlist in the transaction scope. 
    // SubmitChanges now will NOT create a new transaction/commit each time. 
    DoImportStuffThatRunsWithinASingleTransaction(); 
    // Important: Make sure to COMMIT the transaction. 
    // (The transaction used for SubmitChanges is committed to the DB.) 
    // This is when the disk sync actually has to happen, 
    // but it only happens once, not 3500 times! 
    ts.Complete(); 
} 

हालांकि, एक एकल लेनदेन या SubmitChanges के लिए एक एकल कॉल का उपयोग कर एक दृष्टिकोण के शब्दों बुला ऊपर कोड की तुलना में अलग हैं 3500 बार सबमिट करें और 3500 विभिन्न निहित लेनदेन तैयार करें। विशेष रूप से, परमाणु संचालन का आकार (डेटाबेस के संबंध में) अलग है और सभी कार्यों के लिए उपयुक्त नहीं हो सकता है।

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

हैप्पी कोडिंग।

+0

उसको मांसपेशियों के लिए धन्यवाद। मैं linq2sql के लिए ज्यादा नहीं हूँ। +1 –

+0

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

5

मैं इस पर सकारात्मक नहीं हूँ, लेकिन ऐसा लगता है db.SubmitChanges() कॉल की तरह लूप के बाहर किया जाना चाहिए। शायद चीजों को गति देगा?

+0

आप अपनी सोच में बहुत सही हैं! :-) – greenoldman

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