2013-07-01 10 views
3

Я считаю, что я использовал много способов ускорить UPDATE из многих строк, Но пока ничего не помогло.SQLite обновление многих строк очень медленно

Мы открываем сделку, так:

private SQLiteTransaction BeginTransaction(SQLiteConnection connection) 
{ 
    return connection.BeginTransaction(); 
} 

и закрыть его в конце курса. Открываем одно соединение, одну транзакцию, а затем обновляем многие строки в базе данных. Это означает, что мы собираем множество различных операторов SQL в течение нескольких таблиц.

Одна большая часть является обновление 12000 записей в одной таблице

protected override void UpdateRows(SQLiteConnection connection, IEnumerable<DataRow> rowsToUpdate)  
{ 
    var command = new SQLiteCommand(Queries.SQLUpdateDocument, connection); 

     foreach (DataRow documentRow in rowsToUpdate) 
     { 
       command.Parameters.AddWithValue("@Filename", documentRow[Constants.Col_Document_Filename]); 
       command.Parameters.AddWithValue("@ClassID", documentRow[Constants.Col_Document_ClassID]); 
       command.Parameters.AddWithValue("@PageCount", documentRow[Constants.Col_Document_PageCount]); 
       command.Parameters.AddWithValue("@DocID", documentRow[Constants.Col_Document_GlobalDocID]); 
       command.Parameters.AddWithValue("@ReadOnly", documentRow[Constants.Col_Document_ReadOnly]); 
       command.Parameters.AddWithValue("@Confirmed", documentRow[Constants.Col_Document_Confirmed]); 
       command.Parameters.AddWithValue("@ParentFolderID", documentRow[Constants.Col_Document_ParentFolderID]); 
       command.Parameters.AddWithValue("@SequenceNumber", documentRow[Constants.Col_Document_SequenceNumber]); 
       command.Parameters.AddWithValue("@XmlRepr", documentRow[Constants.Col_Document_XmlRepr]); 

       command.ExecuteNonQuery(); 

       documentRow.AcceptChanges(); 
    } 
} 

с неоспоримым запроса:

UPDATE T_Doc SET 
Filename = @Filename, 
ClassID = @ClassID, 
PageCount = @PageCount, 
ReadOnly = @ReadOnly, 
Confirmed = @Confirmed, 
ParentFolderID = @ParentFolderID, 
SequenceNumber = @SequenceNumber, 
XmlRepr = @XmlRepr 
WHERE ID = @DocID; 

в AcceptChanges() не займет много времени. ExecuteNonQuery() намного медленнее, чем ожидалось.

PRAGMA foreign_keys = ON; 

было выполнено до того, как команда обновления и ссылки на ClassID и ParentFolderID ссылаются на другие таблицы.

Anyways - обновление происходит очень медленно, обновление 12000 записей занимает 15-30 минут.

Может ли кто-нибудь помочь мне в этом?

+0

Является ли ваш стол индексированным по полю ID? Если вы можете показать, как вы организуете таблицу, это может помочь понять источник проблемы. – athabaska

+0

попробуйте использовать транзакционную модель: open transaction-> execute ** all ** comands-> commit transaction. – Tigran

+0

@athabaska ID - это первичный ключ. SQLite автоматически создаст первичный ключ. – HankTheTank

ответ

5

Я подозреваю, что вы не звоните BeginTransaction, или, возможно, вы не связываете эту команду с транзакцией ... Если транзакция не указана явно, новый создается неявно каждый раз, когда вы выполняете команду.

Попробуйте это:

protected override void UpdateRows(SQLiteConnection connection, IEnumerable<DataRow> rowsToUpdate)  
{ 
    using (var command = new SQLiteCommand(Queries.SQLUpdateDocument, connection)) 
    using (var transaction = connection.BeginTransaction()) 
    { 
     command.Transaction = transaction; 

     foreach (DataRow documentRow in rowsToUpdate) 
     { 
       command.Parameters.AddWithValue("@Filename", documentRow[Constants.Col_Document_Filename]); 
       command.Parameters.AddWithValue("@ClassID", documentRow[Constants.Col_Document_ClassID]); 
       command.Parameters.AddWithValue("@PageCount", documentRow[Constants.Col_Document_PageCount]); 
       command.Parameters.AddWithValue("@DocID", documentRow[Constants.Col_Document_GlobalDocID]); 
       command.Parameters.AddWithValue("@ReadOnly", documentRow[Constants.Col_Document_ReadOnly]); 
       command.Parameters.AddWithValue("@Confirmed", documentRow[Constants.Col_Document_Confirmed]); 
       command.Parameters.AddWithValue("@ParentFolderID", documentRow[Constants.Col_Document_ParentFolderID]); 
       command.Parameters.AddWithValue("@SequenceNumber", documentRow[Constants.Col_Document_SequenceNumber]); 
       command.Parameters.AddWithValue("@XmlRepr", documentRow[Constants.Col_Document_XmlRepr]); 

       command.ExecuteNonQuery(); 

       documentRow.AcceptChanges(); 
     } 

     transaction.Commit(); 
    } 
} 

Обратите внимание, что если у вас есть очень большое количество строк, вы можете совершить, прежде чем вы обновили все, например, каждые 1000 строк. В этом случае вам нужно создать новую транзакцию после совершения предыдущей.

+1

Мне действительно нужно назначить транзакцию команде?Я полагал, что он был установлен автоматически – HankTheTank

+0

Просто комментарий о концепции совершения транзакций до завершения всей «концептуальной» транзакции. Несмотря на то, что это действительно возможное решение проблемы, вы теряете транзакционную согласованность, которую предоставляет одна транзакция. Поэтому используйте с осторожностью, и я бы посоветовал сделать это только в качестве последнего усилия, чтобы получить производительность вставки в ваших желаемых пределах. Вы очень сильно теряете этот подход. –

+0

@ JakeHeidt, вы правы, но в этом случае использование транзакции в основном является способом повышения производительности, а не способом обеспечения согласованности ... –

Смежные вопросы