Russian Qt Forum

Qt => Базы данных => Тема начата: VAP от Август 27, 2010, 19:14



Название: Как увеличить быстродействие заполнения БД
Отправлено: VAP от Август 27, 2010, 19:14
Решил задать вопрос в разделе БД, т.к. реализацию своей задачи вижу в использовании все же БД. Проблема в следующем: читаю бинарный файл (размер до 20Мб, в среднем размер 10-12Мб), упорядочиваю данные и отображаю через модель в QTableView. Тут  с быстродействием вывода данных все устраивает. Но нужно производить фильтрацию данных, т.е. поиск по критерию(фильтру), таблица имеет 12 полей по которым производится поиск. Попробовал реализовать фильтрацию сразу при чтении, но слишком громоздкий код получается и не рациональный. Удобнее, как мне кажется, заполнить базу данных, а потом производить разные действия с ней фильтруя запросами или QSqlTableModel. Для проверки БД QSQLITE заполняется ну очень медленно ~50000 записей пишутся несколько минут(!), но меня даже одна минута не устраивает. Опыта работы с базами данных у меня мало, потому прошу подсказать какие есть варианты ускорить процесс записи данных? Может все дело в использовании драйвера БД или есть какие-либо методы оптимизации?
 


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: lit-uriy от Август 27, 2010, 20:21
возможно тебе поможет запись данных обернуть в транзакцию, одну на все вставки.


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: kibsoft от Август 27, 2010, 20:37
Может помочь execBatch(), но если СУБД поддерживает. Вот пример. У меня в свое время с 20 с лишним минут снизилось до 9 секунд))
Задание было - распарсить "Война и мир" и запихнуть слова в базу (уникальные).
Код:
QSqlQuery q;
 q.prepare("insert into myTable values (?, ?)");

 QVariantList ints;
 ints << 1 << 2 << 3 << 4;
 q.addBindValue(ints);

 QVariantList names;
 names << "Harald" << "Boris" << "Trond" << QVariant(QVariant::String);
 q.addBindValue(names);

 if (!q.execBatch())
     qDebug() << q.lastError();


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: trot от Август 27, 2010, 20:42
Транзакции не помогут. Если ты для каждой записи из 50000 выполняешь команду insert, то быстродействие не поднимаешь никак.
Для каждого типа СУБД есть различные дополнительные средства решения задачи записи данных большого объема, например в postgres есть команда copy. Поэтому ищи ответ в документации на свою СУБД.


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: eugene от Август 27, 2010, 21:02
Транзакции не помогут. Если ты для каждой записи из 50000 выполняешь команду insert, то быстродействие не поднимаешь никак.
Для каждого типа СУБД есть различные дополнительные средства решения задачи записи данных большого объема, например в postgres есть команда copy. Поэтому ищи ответ в документации на свою СУБД.
А мне вот очень помогли. Скорость заполнения увеличилась существенно, наверное даже на порядок, точно не помню. Поэтому попробовать стоит. Потому что вроде бы для каждого запроса создается отдельная транзакция, что не есть хорошо. Гугли QSqlDatabase::transaction();

Может помочь execBatch(), но если СУБД поддерживает. Вот пример. У меня в свое время с 20 с лишним минут снизилось до 9 секунд))
Задание было - распарсить "Война и мир" и запихнуть слова в базу (уникальные).
Код:
QSqlQuery q;
 q.prepare("insert into myTable values (?, ?)");

 QVariantList ints;
 ints << 1 << 2 << 3 << 4;
 q.addBindValue(ints);

 QVariantList names;
 names << "Harald" << "Boris" << "Trond" << QVariant(QVariant::String);
 q.addBindValue(names);

 if (!q.execBatch())
     qDebug() << q.lastError();

хм... а извлечь таким макаром можно?


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: VAP от Август 27, 2010, 21:59
А SQLITE драйвер поддерживает функцию batch? Не заполняются поля таблицы таким методом.


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: BaltikS от Август 28, 2010, 00:57
Для Sqlite транзакции помогут, например 1 на 100 записей, причём существенно..


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: VAP от Сентябрь 02, 2010, 20:41
Как ни старался я "выжать" быстродействия из SQLITE - ничего не помогло. Перешел на "мускул" и получил результат который более менее устраивает 65435 записей пишутся за ~45 сек. с транзакциями и используя QSqlQuery::execBatch(). Будет время, нужно дальше поэксперементировать с базами данных...

Спасибо всем, кто откликнулся :)


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: MoPDoBoPoT от Сентябрь 02, 2010, 21:39
Что-то ты плохо старался. Только что провёл тест: 20 столбцов, 786432 строк были записаны за 25 секунд (размер файла получился 37797Kb). Правда данные - бинарная таблица (каждый атрибут записи представляет из себя чило: 0 или 1).


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: VAP от Сентябрь 15, 2010, 23:33
Поэкспериментировал с разными базами данных (MySQL, Firebird) и после этого SQLITE "выбросил на свалку", а оказалось зря. Ну, во-первых не в том месте устанавливал завершение транзакции COMMIT(устанавливал до выполнения execBatch(), а нужно было после).
Таким образом связка batch и транзакции дали превосходный результат! Во-вторых эксперименты с БД думаю пошли мне на пользу.:) 
Покопался в инете и нашел интересный материал, может будет интересный для начинающих: http://www.sqlite.org/speed.html  и еще здесь http://habrahabr.ru/blogs/webdev/42121/


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: sne от Сентябрь 16, 2010, 14:59
exec("PRAGMA synchronous=OFF"); Так же как и транзакции существенно прибавляют скорости ;)


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: CroCIV от Сентябрь 17, 2010, 08:35
Что-то ты плохо старался. Только что провёл тест: 20 столбцов, 786432 строк были записаны за 25 секунд (размер файла получился 37797Kb). Правда данные - бинарная таблица (каждый атрибут записи представляет из себя чило: 0 или 1).
А теперь попробуй все то же самое сделать но пусть типы полей будут BLOB и в них какой-нить контент на несколько киллобайт :)

Цитата: VAP
читаю бинарный файл (размер до 20Мб, в среднем размер 10-12Мб)

Из выше изложенного не вижу никакой необходимости подвязывать SQL-сервер, если данные по 20 мегабайт регулярно будут читаться из файла и соваться в специально для них развернутый SQL-сервер и на нем не храниться... А есть возможность хотябы постоянно держать данные на SQL сервере? Не думаю, что тогда возникнет условие пробрасывать 50 000 записей одной транзакцией.

Или я мб все не так понял?


Название: Re: Как увеличить быстродействие заполнения БД
Отправлено: break от Сентябрь 17, 2010, 09:02
в FB для ускорения вставки большого количества записей в таблицу можно было

1) отключить индексы
2) вставить данные
3) включить индексы назад

еще в FB есть опция ForcedWrite отключение которой также повышало быстродействие