Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Разработка баз данных _ Многопоточность при работе с БД

Автор: kibsoft 14.2.2010, 12:17

Есть примерно 58000 записей, я их через execBatch() забиваю в базу (СУБД ORACLE), на это уходит около 4 секунд..вопрос: если например запись в базу разбить на два потока, то можно ускорить запись? Хотя бы теоретически это возможно?

Автор: ViGOur 14.2.2010, 12:32

Это как я понимаю уже нужно обращаться к специфике работы самих БД.
Может не оптимальна настройка самой БД может еще чего...

Автор: Litkevich Yuriy 14.2.2010, 14:14

kibsoft, при вставке больших пачек данных, обычно блокируют (отключают) индексы, а после вставки включают вновь. Т.к. индексация осуществляется во время добавления (вставки) данных

Автор: SABROG 14.2.2010, 15:15

Можно попробовать вызывать BEGIN TRANSACTION перед вставкой, и COMMIT TRANSACTION после. И заливать данные не в таблицу, которую ты собираешься добавлять данные, а сначала во временную, а уже из неё копировать в оригинальную: INSERT INTO TABLE2 SELECT * FROM TABLE1

Автор: kibsoft 15.2.2010, 17:53

Цитата(Litkevich Yuriy @ 14.2.2010, 15:14) *
kibsoft, при вставке больших пачек данных, обычно блокируют (отключают) индексы, а после вставки включают вновь. Т.к. индексация осуществляется во время добавления (вставки) данных


Отключаю, после выполнения запроса вставки включаю, но выдает ошибку:
"ORA-01502: index 'CHASTDICT.WORDIND' or partition of such index is in unusable state

Вот код:
qDebug()<<query.exec("ALTER INDEX WORDIND UNUSABLE");
        query.prepare("INSERT INTO WORDS(WORD,COUNT) VALUES(?,?)");
        keys=QVariant(insertBase.keys()).toList();
        values=insertBase.values();
        query.addBindValue(keys);
        query.addBindValue(values);
        qDebug()<<query.execBatch();
        qDebug()<<query.lastError().databaseText();
        qDebug()<<query.exec("ALTER INDEX WORDIND REBUILD");

Автор: MoPDoBoPoT 15.2.2010, 18:41

Цитата(kibsoft @ 15.2.2010, 17:53) *
...
query.prepare("INSERT INTO WORDS(WORD,COUNT) VALUES(?,?)");
query.addBindValue(keys);
query.addBindValue(values);
...

Так Оракл же даржит именное связывание, а не позиционное. Попробуй так:
        query.prepare("INSERT INTO WORDS(WORD, COUNT) VALUES(:word, :count)");
        keys=QVariant(insertBase.keys()).toList();
        values=insertBase.values();
        query.bindValue(":word", keys);
        query.bindValue(":count", values);
        qDebug()<<query.execBatch();

Автор: kibsoft 15.2.2010, 19:17

Цитата(MoPDoBoPoT @ 15.2.2010, 19:41) *
Цитата(kibsoft @ 15.2.2010, 17:53) *
...
query.prepare("INSERT INTO WORDS(WORD,COUNT) VALUES(?,?)");
query.addBindValue(keys);
query.addBindValue(values);
...

Так Оракл же даржит именное связывание, а не позиционное. Попробуй так:
        query.prepare("INSERT INTO WORDS(WORD, COUNT) VALUES(:word, :count)");
        keys=QVariant(insertBase.keys()).toList();
        values=insertBase.values();
        query.bindValue(":word", keys);
        query.bindValue(":count", values);
        qDebug()<<query.execBatch();



Не в этом дело..без отлючения/влючения индекса и с позиционным работает...но дольше вставка идет чем без индекса, но зато обновление базы с индексом намного быстрее.. вот я и хочу на время вствки его отключать, но видимо так нельзя..

Автор: Litkevich Yuriy 15.2.2010, 19:38

kibsoft, ты транзакции используешь?

Автор: MoPDoBoPoT 15.2.2010, 20:07

Цитата(kibsoft @ 15.2.2010, 19:17) *
Не в этом дело..без отлючения/влючения индекса и с позиционным работает...но дольше вставка идет чем без индекса, но зато обновление базы с индексом намного быстрее.. вот я и хочу на время вствки его отключать, но видимо так нельзя..

Я в курсе. Конечной целью у тебя является увеличить скорость записи данных в БД, потому я и сделал замечание. Собственно, подготовка запроса (prepare) служит для того, чтобы СУБД разобрало текст запроса один раз и поместила его в библиотечный кэш, а пользовалось им много раз (сам разбор запроса занимает некоторое время).
Насчет индексов - спроси про это на sql.ru, там прохаванные в этом люди.
Цитата(Litkevich Yuriy @ 15.2.2010, 19:38) *
kibsoft, ты транзакции используешь?

Так он же execBatch() пользуется, там уже оптимизировано в этом плане.

Автор: Litkevich Yuriy 15.2.2010, 20:24

Цитата(MoPDoBoPoT @ 15.2.2010, 23:07) *
там уже оптимизировано в этом плане.
вот не могу вспомнить/найти, где это обсуждалось. Явное использование транзакции помогало ускорить процесс.

Автор: kibsoft 15.2.2010, 20:45

Не явно их не использую..а как beginTransaction() у QSqlDriver?
просто в БД я вообще не силен, по ним ничего толком не читал..

Автор: MoPDoBoPoT 15.2.2010, 21:07

Цитата(Litkevich Yuriy @ 15.2.2010, 20:24) *
вот не могу вспомнить/найти, где это обсуждалось. Явное использование транзакции помогало ускорить процесс.

Ну да, при последовательном выполнении инструкций, но здесь используется execBatch(), который поддерживается Ораклом. В этом случае данные пакуются в массивы и передаются на сервер, где уже вставляются. По-моему так :)

Но попробовать явно начать-закончить транзакцию все равно стоит, а то мало ли (:

Автор: Litkevich Yuriy 15.2.2010, 21:20

Цитата(MoPDoBoPoT @ 16.2.2010, 0:07) *
Но попробовать явно начать-закончить транзакцию все равно стоит, а то мало ли (:
тем более, что это не сложно:
QSqlDatabase::database().transaction();
...
QSqlDatabase::database().commit();

Автор: kibsoft 15.2.2010, 21:35

Цитата(Litkevich Yuriy @ 15.2.2010, 22:20) *
Цитата(MoPDoBoPoT @ 16.2.2010, 0:07) *
Но попробовать явно начать-закончить транзакцию все равно стоит, а то мало ли (:
тем более, что это не сложно:
QSqlDatabase::database().transaction();
...
QSqlDatabase::database().commit();



При явном указании ничего не изменилось :(
На sql.ru дали вот такой запрос:
alter session set skip_unusable_indexes=true, ошибка теперь не выводится и execBatch() возвращает true, но данные в таблицу не заносятся :huh:

Автор: MoPDoBoPoT 18.2.2010, 19:02

Чем, собственно, все закончилось?

Автор: kibsoft 20.2.2010, 0:19

Цитата(MoPDoBoPoT @ 18.2.2010, 20:02) *
Чем, собственно, все закончилось?

Кончилось все хорошо, с 6 секунд парсинга и записи в БД "Войны и мир" ускорил до 1,6 :)

Автор: Litkevich Yuriy 20.2.2010, 0:58

Цитата(kibsoft @ 20.2.2010, 3:19) *
Кончилось все хорошо, с 6 секунд парсинга и записи в БД "Войны и мир" ускорил до 1,6
чем ускорил?

Автор: kibsoft 20.2.2010, 12:46

Цитата(Litkevich Yuriy @ 20.2.2010, 1:58) *
Цитата(kibsoft @ 20.2.2010, 3:19) *
Кончилось все хорошо, с 6 секунд парсинга и записи в БД "Войны и мир" ускорил до 1,6
чем ускорил?

Все оставил прежним, но индекс сделал не уникальным(уникальность у меня проверяется в программе). Ну и убрал лишний столбец ID с автоинкрементом(незнаю зачем вообще его в данном случае делал..)

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)