проблема производительности фиксации sqlite с индексами - PullRequest
0 голосов
/ 09 июня 2011

Я столкнулся с проблемой, когда время выполнения коммита начинается все дольше и дольше.Мы говорим о 250 миллисекундах для стола с ~ 20 тысячами строк и размером диска около 2-3 миллионов.И это только ухудшается.Я отследил проблему с производительностью, связанную с индексами.Как будто sqlite создает индекс при каждом коммите.Коммит состоит из 100 INSERTS.Я сделал настолько маленькую программу, насколько мог, чтобы воспроизвести проблему, и попытался запустить ее и в Linux.Там, похоже, проблема не возникает.Проблема существует как в режиме WAL, так и в режиме усечения журналирования.Проблема, кажется, не существует, когда я использую базу данных памяти вместо файла.Я пробовал обе версии 3.6.23.1 и 3.7.6.3.

В Windows, где я испытываю проблему, я запускаю sqlite в программе на C #.Я проверил реализацию поддержки транзакций в оболочке System.Date.Sqlite, и она не делает ничего другого, кроме просто COMMIT.К сожалению, у меня нет компилятора C для Windows, поэтому я не могу проверить его, когда не запущена оболочка, но он должен быть таким же.

System.IO.File.Delete("test.db");

var db_connection = new SQLiteConnection(@"Data Source=test.db");

db_connection.Open();

using (var cmd = db_connection.CreateCommand())
{
    cmd.CommandText = "CREATE TABLE test (id integer primary key, dato integer)";
    cmd.ExecuteNonQuery();
    cmd.CommandText = "CREATE INDEX i on test(dato)";
    cmd.ExecuteNonQuery();
}

SQLiteTransaction trans = null;

List<string> paths = new List<string>();

var random = new Random();

for (var j = 0; j < 150; ++j)
{
    for (var i = 0; i < 1000; ++i)
    {
        if (i % 100 == 0)
        {
            trans = db_connection.BeginTransaction();
        }

        using (var cmd = db_connection.CreateCommand())
        {
            cmd.CommandText = String.Format("INSERT INTO test (dato) values ({0})", random.Next(1, 100000000));
            cmd.ExecuteNonQuery();
        }

        if (i % 100 == 99 && trans != null)
        {
            var now = DateTime.Now;

            trans.Commit();
            trans.Dispose();

            System.Console.WriteLine("commit {0}", (DateTime.Now - now).TotalMilliseconds);
        }
    }
}

1 Ответ

0 голосов
/ 13 января 2012

Вы пытались уменьшить доступ к жесткому диску, например, добавив эту команду перед созданием любой таблицы:

cmd.CommandText = "PRAGMA locking_mode = EXCLUSIVE";
cmd.ExecuteNonQuery();

Предоставление вашему приложению допускает монопольную блокировку базы данных.

Также может помочь:

PRAGMA Synchronous=OFF
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...