Производительность SQLite .NET, как ускорить работу?
В моей системе ~ 86000 вставок SQLite занимали до 20 минут, это означает ~ 70 вставок в секунду. Я должен делать миллионы, как я могу ускорить его? Вызов Open () и Close () объекта SQLiteConnection для каждой строки может замедлить производительность? Могут ли транзакции помочь?
Типичный метод вставки для одной строки:
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; }
Как вы можете видеть, вставки очень простые.
- Поддерживает ли Android поддержку JDBC
- измените размер файла sqlite после «DELETE FROM table»
- Как проверить, существует ли таблица в базе данных Android SQLite?
- Использование оператора LIMIT в SQLite-запросе
- Чистый способ найти объекты ActiveRecord по идентификатору в указанном порядке
- Как просмотреть данные, сохраненные в базе данных Android (SQLite)?
- Синхронизация клиентской базы данных SQLite с базой данных сервера MySQL
- hibernate на две группы на одну сущность
- SQLite Modify Column
- Ошибка приложения при запуске из-за java.lang.IllegalArgumentException: column '_id' не существует
- Получить последнее вставленное значение из базы данных sqlite Android
- System.Data.SQLite Close () не освобождает файл базы данных
- Как получить данные из базы данных sqlite в android и отобразить ее в TextView
Вам определенно нужна сделка. Если вы этого не сделаете, SQLite начнет свою собственную транзакцию для каждой команды вставки, чтобы эффективно выполнять 86000 транзакций.
Кажется, вы также открываете и закрываете соединение каждый раз, а также каждый раз перезагружаете CommandText. Это не нужно и, несомненно, замедляет вас, это будет намного быстрее, если вы:
- Откройте соединение один раз
- Создайте команду один раз, добавив параметры к ней один раз.
- Запустить транзакцию
- Прокрутите, измените значения параметров только до вызова 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(); }
Он использует только одно соединение, одну транзакцию и одну команду, поэтому все, что вы меняете, это значения параметров каждый раз.
Используйте транзакции. Это должно ускорить работу. Также я бы порекомендовал вам следующую схему:
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; } } }