Столкнулся с проблемой долгого выполнения большого количества INSERT в SQLite базу. В результате ниже описанного изменения кода получил увеличение скорости почти в 2 раза.
Гугл не дал внятных примеров, особенно на .Net, что и вызвало желание написать данный пост, надеюсь, поможет кому-нить от геморроя.
Все под катом, так как не представляет никакого интереса для среднестатистического человека.
Первоначально код выглядел так :
if (reader.count > 0) //некие данные, которые надо записать
{
int iProgress = 0;
beginProgress(reader.count); //ПрогрессБар
try
{
using (SQLiteCommand cmd = m_db.createCommand())
{
cmd.CommandText = @"INSERT ….. VALUES (…..)";
SQLiteParameter Param = new SQLiteParameter("@name", DbType.Int32);
…
cmd.Parameters.Add(Param);// обработкапараметров
……
cmd.Prepare();
myDataset.myTableRow src = myDataset.myTable.NewRow();
while (reader.read(src))
{
Param.Value = src.gid;
goods_gidParam.Value = src[name];
…..
cmd.ExecuteNonQuery();
iProgress++;
setProgress(iProgress);
}
}
}
finally
{
endProgress();
}
}
Но 4к-6к итераций данного while выполнялся 4-6 минут, что не есть хорошо. Изучая особенности SqLite базы выяснилось, что есть некая команда Pragma, в которой можно задать всякие вкусняшки типа кодировки данных и т д.
В том числе некую синхронизация. Как оказалось, SqLite - редкий параноик и не доверяет командам пользователя, оборачивая каждую из них в отдельную транзакцию, которая ,собствено, и тормозит весь процесс.
По умолчанию
PRAGMA synchronous=Normal что означает:а не поверю я тебе и защитю данные транзакцией.
В результате наш код был изменен
if (reader.count > 0)
{
int iProgress = 0;
beginProgress(reader.count);
try
{
using (SQLiteCommand cmd = m_db.createCommand())
{
m_db.beginTransaction();
cmd.CommandText = " PRAGMA synchronous=OFF"; //Все ОК! доверяй этой транзакции
cmd.ExecuteNonQuery();
cmd.CommandText = @"INSERT … VALUES( …)";
SQLiteParameter Param = new SQLiteParameter("@name", DbType.Int32); //обработа параметров
…
cmd.Parameters.Add(Param);
……
cmd.Prepare();
myDataset.myTableRow src = myDataset.myTable.NewRow();
while (reader.read(src))
{
Param.Value = src.gid;//обработа параметров
goods_gidParam.Value = src[name];
cmd.ExecuteNonQuery();
iProgress++;
setProgress(iProgress);
}
m_db.commitTransaction();
}
}
finally
{
endProgress();
m_db.cancelTransaction();
}
}
О полезностях SQLite читаем на родном сайте