Rendimiento SQLite .NET, ¿cómo acelerar las cosas?

En mi sistema, ~ 86000 inserciones SQLite tomaron hasta 20 minutos, significa ~ 70 inserciones por segundo. Tengo que hacer millones, ¿cómo puedo acelerarlo? ¿Llamar a Open () y Close () en el objeto SQLiteConnection para cada línea puede ralentizar el rendimiento? ¿Pueden las transacciones ayudar?

Método de inserción típico para una sola línea:

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; } 

Como puede ver, las inserciones son muy simples.

Definitivamente necesitas una transacción. Si no lo hace, SQLite inicia su propia transacción para cada comando de inserción, por lo que efectivamente está haciendo 86000 transacciones como está.

Parece que también estás abriendo y cerrando la conexión cada vez, junto con restablecer el CommandText cada vez. Esto es innecesario y sin duda te frena, irá mucho más rápido si tú:

  • Abra la conexión una vez
  • Construya el comando una vez, agregándole los parámetros una vez.
  • Comience la transacción
  • Recorra, cambiando los valores de los parámetros solo antes de llamar a ExecuteNonQuery
  • Confirmar la transacción
  • Cierra la conexión.

Creo que podrías reducir tus 20 minutos a solo unos segundos de esta manera.

Editar: esto es lo que quiero decir:

 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(); } 

Solo usa una conexión, una transacción y un comando, por lo que todo lo que cambia son los valores de los parámetros cada vez.

Usa transacciones Esto debería hacer las cosas más rápido. También te recomendaría el siguiente patrón:

 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; } } }