Russian Qt Forum
Сентябрь 30, 2024, 18:38 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как увеличить быстродействие заполнения БД  (Прочитано 12753 раз)
VAP
Гость
« : Август 27, 2010, 19:14 »

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

Сообщений: 3880


Просмотр профиля WWW
« Ответ #1 : Август 27, 2010, 20:21 »

возможно тебе поможет запись данных обернуть в транзакцию, одну на все вставки.
Записан

Юра.
kibsoft
Хакер
*****
Offline Offline

Сообщений: 625


Просмотр профиля WWW
« Ответ #2 : Август 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();
« Последнее редактирование: Август 27, 2010, 20:39 от kibsoft » Записан

http://kibsoft.ru - Download the Qt Media Encoding Library here

The apps that were written using QtMEL:
http://srecorder.com - Screen recording software
trot
Гость
« Ответ #3 : Август 27, 2010, 20:42 »

Транзакции не помогут. Если ты для каждой записи из 50000 выполняешь команду insert, то быстродействие не поднимаешь никак.
Для каждого типа СУБД есть различные дополнительные средства решения задачи записи данных большого объема, например в postgres есть команда copy. Поэтому ищи ответ в документации на свою СУБД.
Записан
eugene
Гость
« Ответ #4 : Август 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();

хм... а извлечь таким макаром можно?
« Последнее редактирование: Август 27, 2010, 21:37 от eugene » Записан
VAP
Гость
« Ответ #5 : Август 27, 2010, 21:59 »

А SQLITE драйвер поддерживает функцию batch? Не заполняются поля таблицы таким методом.
Записан
BaltikS
Гость
« Ответ #6 : Август 28, 2010, 00:57 »

Для Sqlite транзакции помогут, например 1 на 100 записей, причём существенно..
Записан
VAP
Гость
« Ответ #7 : Сентябрь 02, 2010, 20:41 »

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

Спасибо всем, кто откликнулся Улыбающийся
Записан
MoPDoBoPoT
Гость
« Ответ #8 : Сентябрь 02, 2010, 21:39 »

Что-то ты плохо старался. Только что провёл тест: 20 столбцов, 786432 строк были записаны за 25 секунд (размер файла получился 37797Kb). Правда данные - бинарная таблица (каждый атрибут записи представляет из себя чило: 0 или 1).
Записан
VAP
Гость
« Ответ #9 : Сентябрь 15, 2010, 23:33 »

Поэкспериментировал с разными базами данных (MySQL, Firebird) и после этого SQLITE "выбросил на свалку", а оказалось зря. Ну, во-первых не в том месте устанавливал завершение транзакции COMMIT(устанавливал до выполнения execBatch(), а нужно было после).
Таким образом связка batch и транзакции дали превосходный результат! Во-вторых эксперименты с БД думаю пошли мне на пользу.Улыбающийся 
Покопался в инете и нашел интересный материал, может будет интересный для начинающих: http://www.sqlite.org/speed.html  и еще здесь http://habrahabr.ru/blogs/webdev/42121/
Записан
sne
Гость
« Ответ #10 : Сентябрь 16, 2010, 14:59 »

exec("PRAGMA synchronous=OFF"); Так же как и транзакции существенно прибавляют скорости Подмигивающий
Записан
CroCIV
Гость
« Ответ #11 : Сентябрь 17, 2010, 08:35 »

Что-то ты плохо старался. Только что провёл тест: 20 столбцов, 786432 строк были записаны за 25 секунд (размер файла получился 37797Kb). Правда данные - бинарная таблица (каждый атрибут записи представляет из себя чило: 0 или 1).
А теперь попробуй все то же самое сделать но пусть типы полей будут BLOB и в них какой-нить контент на несколько киллобайт Улыбающийся

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

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

Или я мб все не так понял?
« Последнее редактирование: Сентябрь 17, 2010, 08:39 от CroCIV » Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #12 : Сентябрь 17, 2010, 09:02 »

в FB для ускорения вставки большого количества записей в таблицу можно было

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

еще в FB есть опция ForcedWrite отключение которой также повышало быстродействие
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.071 секунд. Запросов: 22.