LINUX.ORG.RU

Открываем мир БД

 , , ,


0

1

Есть класс, назовем его MySqlClass, который подключается к БД(MySQL); У MySqlClass есть слот вида

void write(string x, string y, string z);
Собственно слот записывает в нужную таблицу эти самые x, y и z через QSqlQuery.
(INSERT INTO table VALUES(:x,:y,:z))

Есть другой класс, назовем его MyDataGenerator, который работает в несколько потоков: читает файлы, парсит их, проводит всякие операции над ними и генерирует x, y и z для каждого файла, после чего испускает сигнал который идет в объект класса MySqlClass.

Вопросы:

  • как быстрее писать в БД?
  • создавать при каждом вызове новое подключение к БД?
  • запускать каждый QSqlQuery в новом потоке?
  • А может накапливать n запросов а потом кучкой их выполнять?
★★★

Последнее исправление: BruteForce (всего исправлений: 1)

как быстрее писать в БД?

зависит от, сильно. Индексы, ограничения уникальности, ключи, автоинкременты, движки хранения итд.

создавать при каждом вызове новое подключение к БД?

для производительности - однозначно нет.

запускать каждый QSqlQuery в новом потоке?

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

А может накапливать n запросов а потом кучкой их выполнять?

однозначно да. Причем накапливать именно оные values, а потом загонять одним инсертом.

ну и в общем - погуглить про mysql bulk insert

arkhnchul ★★★
()
Ответ на: комментарий от arkhnchul

однозначно да. Причем накапливать именно оные values, а потом загонять одним инсертом.

А по сколько их загонять? Или прям накопить-накопить и одним инсертом? Но, я полагаю, нужно отталкиваться от того, что «накапливалка» сломается (память кончится).

ну и в общем - погуглить про mysql bulk insert

Благодарю, нашел реализацию.

BruteForce ★★★
() автор топика
Ответ на: комментарий от BruteForce

А по сколько их загонять?

чем больше, тем лучше.

Но, я полагаю, нужно отталкиваться от того, что «накапливалка» сломается (память кончится).

ну до этого доводить не нужно конечно. Мало того, память нужна самой СУБД, т.ч. оставь и ей, а то вставлять будет наоборот медленнее, если ты всю память съешь.

Или прям накопить-накопить и одним инсертом?

в mysql есть транзакции вообще-то.

emulek
()

как быстрее писать в БД?

А может накапливать n запросов а потом кучкой их выполнять?

Что будет если твой процесс упадет и не сможет записать? Если особо ничего страшного и процес сможет востановиться и начать с места падения, то просто создай отдельный поток и накапливай в нем данные. Когда накопится достаточно, то я бы рекомендовал batch insert

P.S. В MySQL не разбираюсь, но СУБД обычно очень радуются от пакетной вставки

создавать при каждом вызове новое подключение к БД?

В документации указано являются ли подключения stateless и thread-safe. Если да, то можно, если нет, то есть такая штука как connection pool. Гугли

vertexua ★★★★★
()
Ответ на: комментарий от BruteForce

Но, я полагаю, нужно отталкиваться от того, что «накапливалка» сломается (память кончится).

Оцени размер своих данных, добавь необходимые валидации. Учти, что есть размер данных, как правило небольшой, даже не больше мегабайта, после которого увеличение max batch size не особо что-то дает

vertexua ★★★★★
()
Ответ на: комментарий от vertexua

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

я с мускулем одно время извращался - писал значения в файл на рамдиске, а потом натравливал на него LOAD DATA INFILE вместо INSERT-а (нету вроде до сих пор в мускуля аналога постгресного COPY FROM STDIN)

arkhnchul ★★★
()
  • Проводить записи по 100к-1M строчек за одну транзакцию
  • Использовать не больше 16-30 одновременно работающих соединений к mysql
  • Использовать мульти запросы (insert into a values (1),(2),(3)...), стараться не превышать 8-64МБ за один запрос либо использовать csv+load data in file
  • если bulk load много данных лопатит (как минимум несколько мегабайт за сессию) то без разницы будет ли коннект постоянный или по-одному на серию запросов
  • У mysql синхронная клиентская библиотека, чтобы не залипать, надо использовать отдельные потоки, каждый поток должен прокачивать много запросов, желательно чтобы запросы он получал сразу группами а не по одной строчке
  • Не забыть настроить mysql, протестировать производительность, сравнить с тестами в инете на аналогичном железе
  • желательно raid+bbu
anonymous
()
Ответ на: комментарий от BruteForce

в Qt не нашел искаробочного класса, в простейшем случае делается коллекция из N инстансов QSqlDatabase и метод get() который берет подключение, помечает его занятым и отдает.

x0r ★★★★★
()
Последнее исправление: x0r (всего исправлений: 1)
Ответ на: комментарий от arkhnchul

Для mysql в общем такие рекоммендации. Использовать транзакции, использовать prepared statements.

bulk insert особых приростов не дадут, в сравнении с транзакциями, можно попробовать insert delayed.

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

hidden_4003
()

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

vazgen05 ★★★
()
Ответ на: комментарий от hidden_4003

Использовать транзакции, использовать prepared statements.

bulk insert особых приростов не дадут, в сравнении с транзакциями, можно попробовать insert delayed.

LOAD DATA для кучи данных все равно быстрее инсертов, как с ними не извращайся. Ну и тс не сказал, что у него там - myisam или innodb, будет толк от транзакций и delayed или нет - вопрос. Равно же как и с ключами - а ну как там одна табличка (x,y,z) без ничего вообще.

arkhnchul ★★★
()
Ответ на: комментарий от vazgen05

Всегда было интересно, а в этих ваших эскуэлях запрос всегда идет в текстовом виде?

нет.

arkhnchul ★★★
()
Ответ на: комментарий от arkhnchul

LOAD DATA требует привилегий

to use LOAD DATA INFILE on server files, you must have the FILE privilege.

С bulk insert надо контролировать размер запроса чтобы не превысить max_packet_size иначе будет server has gone away.

Но до тех пор пока не озвучено количество загружаемых строк и структура таблицы сложно сказать что-то более конкретное.

hidden_4003
()
Ответ на: комментарий от bvn13

http://www.databaseskill.com/4931524/

  
   
   

  The QSqlQuery Q; 
  q.prepare ("insert into student values ??(?,?)"); 

  QVariantList ints; ints << 10 << 11 << 12 << 13; 

  q.addBindValue (ints); 

  QVariantList names; names << "xiaoming" << "xiaoliang" << "xiaogang" << 

  QVariant (QVariant :: String); / / last is an empty string, with the same format as the previous 

  q.addBindValue (names); 
  if (! q.execBatch ()) / / batch processing, if an error occurs on the output error 

  qDebug It () the << q.lastError ();    

BruteForce ★★★
() автор топика
Ответ на: комментарий от hidden_4003

Но до тех пор пока не озвучено количество загружаемых строк и структура таблицы сложно сказать что-то более конкретное.

вот в том-то и. Можт там вообще смешная нагрузка, ради которой заморачиваться бессмысленно. ТС, ау.

arkhnchul ★★★
()
Ответ на: комментарий от arkhnchul

ТС, ау.

Задачи на самом деле никакой нет, я просто пробую разобраться с БД. И таблицу могу любую нарисовать и пр.

BruteForce ★★★
() автор топика
Ответ на: комментарий от vazgen05

То бишь, если мне понадобится закинуть в табличку сотни чисел, то они пока дойдут до диска десять раз сконвертируются в числовое/текстовое представление?

там время конвертации пренебрежимо мало. Больше всего времени тратиться на работу с индексом, даже если индекс целиком влезает в память.

А если не использовать индекс, то и смысла в СУБД нет никакого.

Т.о. оверхед от конвертации из текста минимальный.

emulek
()
Ответ на: комментарий от arkhnchul

Равно же как и с ключами - а ну как там одна табличка (x,y,z) без ничего вообще.

тогда проще юзать простой файл, и вообще не использовать СУБД.

emulek
()
Ответ на: комментарий от BruteForce

Задачи на самом деле никакой нет, я просто пробую разобраться с БД. И таблицу могу любую нарисовать и пр.

в таком случае делай по одному INSERT'у, и не парь мозги. Вот когда начнутся проблемы — будешь думать. Помни, что преждевременная оптимизация это всегда зло.

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.