2010-12-04 14 views
12

मेरे सिस्टम पर, ~ 86000 एसक्यूएलएट सम्मिलन में 20 मिनट तक लगने का मतलब है, प्रति सेकंड ~ 70 प्रविष्टियां। मुझे लाखों करना है, मैं इसे कैसे बढ़ा सकता हूं? प्रत्येक पंक्ति के लिए SQLiteConnection ऑब्जेक्ट पर ओपन() और बंद() को कॉल करना प्रदर्शन को धीमा कर सकता है? लेनदेन मदद कर सकते हैं? एक लाइन के लिएSQLite .NET प्रदर्शन, चीजों को कैसे गति दें?

ठेठ प्रविष्टि विधि:

public int InsertResultItem(string runTag, int topicId, 
     string documentNumber, int rank, double score) 
    { 
     // Apre la connessione e imposta il comando 
     connection.Open(); 

     command.CommandText = "INSERT OR IGNORE INTO Result " 
      + "(RunTag, TopicId, DocumentNumber, Rank, Score) " + 
      "VALUES (@RunTag, @TopicId, @DocumentNumber, @Rank, @Score)"; 

     // Imposta i parametri 
     command.Parameters.AddWithValue("@RunTag", runTag); 
     command.Parameters.AddWithValue("@TopicId", topicId); 
     command.Parameters.AddWithValue("@DocumentNumber", documentNumber); 
     command.Parameters.AddWithValue("@Rank", rank); 
     command.Parameters.AddWithValue("@Score", score); 

     // Ottieni il risultato e chiudi la connessione 
     int retval = command.ExecuteNonQuery(); 
     connection.Close(); 

     return retval; 
    } 

आप देख सकते हैं, सम्मिलन बहुत सरल होते हैं।

उत्तर

23

आपको निश्चित रूप से एक लेनदेन की आवश्यकता है। यदि आप नहीं करते हैं, तो SQLite प्रत्येक सम्मिलन आदेश के लिए अपना लेनदेन शुरू करता है ताकि आप प्रभावी रूप से 86000 लेनदेन कर रहे हों।

ऐसा लगता है कि आप प्रत्येक बार कमांडटेक्स्ट को रीसेट करने के साथ-साथ कनेक्शन को खोल और बंद कर रहे हैं। यह अनावश्यक और निस्संदेह आप धीमा है, यह बहुत तेजी से जाना होगा यदि आप:

  • ओपन कनेक्शन एक बार
  • एक बार बनाएं आदेश, एक बार इसे करने के लिए पैरामीटर जोड़कर।
  • केवल बुला ExecuteNonQuery
  • लेनदेन प्रतिबद्ध से पहले, के माध्यम से लेन-देन
  • लूप प्रारंभ पैरामीटर मान बदलते।
  • कनेक्शन बंद करें।

मुझे लगता है कि आप इस तरह से कुछ मिनटों तक अपने 20 मिनट नीचे कम कर सकते हैं।

संपादित करें:

public void InsertItems() 
{ 
    SQLiteConnection connection = new SQLiteConnection(SomeConnectionString); 
    SQLiteCommand command = connection.CreateCommand(); 
    SQLiteTransaction transaction = connection.BeginTransaction(); 

    command.CommandText = "INSERT OR IGNORE INTO Result " 
+ "(RunTag, TopicId, DocumentNumber, Rank, Score) " + 
    "VALUES (@RunTag, @TopicId, @DocumentNumber, @Rank, @Score)"; 

    command.Parameters.AddWithValue("@RunTag", ""); 
    command.Parameters.AddWithValue("@TopicId", ""); 
    command.Parameters.AddWithValue("@DocumentNumber", ""); 
    command.Parameters.AddWithValue("@Rank", ""); 
    command.Parameters.AddWithValue("@Score", ""); 

    foreach (/* item to loop through and add to db */) 
    { 
     InsertResultItem(runTag, topicId, documentNumber, rank, score, command); 
    } 

    transaction.Commit(); 
    command.Dispose(); 
    connection.Dispose(); 
} 

public int InsertResultItem(string runTag, int topicId, string documentNumber, int rank, double score, SQLiteCommand command) 
{ 
    command.Parameters["@RunTag"].Value = runTag; 
    command.Parameters["@TopicId"].Value = topicId; 
    command.Parameters["@DocumentNumber"].Value = documentNumber; 
    command.Parameters["@Rank"].Value = rank; 
    command.Parameters["@Score"].Value = score; 
    return command.ExecuteNonQuery(); 
} 

यह केवल एक कनेक्शन, एक लेन-देन और एक आदेश है, तो तुम सब बदल रहे हैं पैरामीटर मान हर बार है का उपयोग करता है: यह मैं क्या मतलब है।

+0

कैंट 'समझ बिंदु # 2, क्या आप समझा सकते हैं? – gremo

+0

@Gremo, मैंने इसे एक उदाहरण दिखाने के लिए संपादित किया है। – mikel

+0

मैं नहीं कर सकता, सिर्फ इसलिए कि लूप किसी अन्य वर्ग में है ... IDISposable को लागू करने और निपटान() पर लेनदेन करने के बारे में कैसे? – gremo

3

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

public int InsertResultItem(string runTag, int topicId, 
    string documentNumber, int rank, double score) 
{ 
    // Apre la connessione e imposta il comando 
    using (var connection = new SQLiteConnection(SomeConnectionString)) 
    using (var command = new connection.CreateCommand()) 
    { 
     connection.Open(); 
     using (var tx = connection.BeginTransaction()) 
     { 
      command.CommandText = "INSERT OR IGNORE INTO Result " 
       + "(RunTag, TopicId, DocumentNumber, Rank, Score) " + 
       "VALUES (@RunTag, @TopicId, @DocumentNumber, @Rank, @Score)"; 

      // Imposta i parametri 
      command.Parameters.AddWithValue("@RunTag", runTag); 
      command.Parameters.AddWithValue("@TopicId", topicId); 
      command.Parameters.AddWithValue("@DocumentNumber", documentNumber); 
      command.Parameters.AddWithValue("@Rank", rank); 
      command.Parameters.AddWithValue("@Score", score); 

      // Ottieni il risultato e chiudi la connessione 
      var retval = command.ExecuteNonQuery(); 
      tx.Commit(); 
      return retval; 
     } 
    } 
} 
+0

InsertResultItem जैसा लगता है कि इसे लूप में बुलाया जाएगा, यह अभी भी एक नया कनेक्शन खोल रहा है, एक नया लेनदेन शुरू कर रहा है और प्रत्येक डालने के लिए एक नया आदेश बना रहा है। गति ओपी के कोड के समान ही होगी। – mikel

+0

@ miket2e, यह एक नया कनेक्शन नहीं खोल रहा है, ADO.NET कनेक्शन पूल का उपयोग करता है। एक नया लेनदेन शुरू करना बिल्कुल चीजों को गति देता है। –

+0

हालांकि यह प्रत्येक डालने के लिए एक लेनदेन बना रहा है। SQLite यह वैसे भी करता है (http://www.sqlite.org/lang_transaction.html) यदि आप इसे स्पष्ट रूप से नहीं बताते हैं, तो इसका मतलब यह है कि यह वही है। एक अंतर बनाने के लिए सभी आवेषणों के चारों ओर लपेटकर एक लेनदेन होना आवश्यक है। मुझे यकीन नहीं है कि क्या वह ADO.NET का उपयोग कर रहा है या नहीं, अगर वह किसी एप्लिकेशन में एम्बेडेड SQLite का उपयोग कर रहा है (ADO.NET के बिना) तो यह एक बार भी कनेक्ट हो जाएगा। – mikel

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