Массовая вставка данных в SQLQuery, получить итоговый запрос

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Массовая вставка данных в SQLQuery, получить итоговый запрос

Сообщение Ism » 31.01.2013 21:41:52

Привет
Необходимо вставить сразу более 20000 записей. Но вот проблема, SQLQuery в режиме CachedUpdates:=true по ApplyUpdates применяет вставку по одному insert, что гораздо медленнее , чем просто бросить скрипт вставки на сервер и там выполнить
Сервер MySql
Есть ли возможность получить скрипт вставки из DataSet не отправляя данные, а потом отправить на сервер через ExecuteDirect ?

Можно конечно сформировать запрос вручную, но это неудобно
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Padre_Mortius » 31.01.2013 22:01:31

данные вы откуда берете?

если из таблицы. то вроде была возможность использовать что-то вроде
Код: Выделить всё
insert into table select * from table2 where ...
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Ism » 31.01.2013 22:14:31

Padre_Mortius писал(а):данные вы откуда берете?

если из таблицы. то вроде была возможность использовать что-то вроде
Код: Выделить всё
insert into table select * from table2 where ...

Тут все проблематично, данные берутся из одной базы(не MySql) и сливаются в другую, поэтому единственный вариант брать запись из одной базы и бросать в другую.
Ускорить можно только бросая пакетами, и как заставить SQLQuery это делать непонятно
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Padre_Mortius » 31.01.2013 23:13:49

Можно попробовать несколько Insert-запросов обрамить в
Код: Выделить всё
BEGIN TRANSACTION;
INSERT ...;
INSERT ...;
COMMIT TRANSACTION;

Я делал похожим образом для sqlite, но там пользовался их API, а не SQLQuery (причину уже не помню)
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Ism » 31.01.2013 23:28:40

Padre_Mortius писал(а):Можно попробовать несколько Insert-запросов обрамить в
Код: Выделить всё
BEGIN TRANSACTION;
INSERT ...;
INSERT ...;
COMMIT TRANSACTION;

Я делал похожим образом для sqlite, но там пользовался их API, а не SQLQuery (причину уже не помню)


В этом проблемы нет, проблема в том, что один insert на строку даже в транзакции медленно передается и выполняется,
Единственный вариант это
insert ...
values
(1,2,3)
(6,7,8)

И так далее, если бросить такой запрос на сервер одной командой, то это будет на порядок быстрее

Просто SQLQuery не умеет бросать на сервер insert скопом, похоже придется вручную формировать
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Padre_Mortius » 31.01.2013 23:33:29

Если к TSQLQuery подключен TTransactionSQL, то должно очень быстро выполняться...
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Ism » 31.01.2013 23:34:45

Padre_Mortius писал(а):Если к TSQLQuery подключен TTransactionSQL, то должно очень быстро выполняться...

Дело не в транзакции, а в том, что по одному insert медленнее, чем вариант указанный выше
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Padre_Mortius » 31.01.2013 23:45:45

Разве при оформлении в явную транзакцию сервер должен ее разбивать эту транзакцию на более мелкие коммиты? К транзакции вроде должен применяться только один коммит в конце если нет ошибок, или rollback если произошла ошибка. И параметра CachedUpdates у TSQLQuery не нашел (Лазарь 1.1 из свн)

Добавлено спустя 5 минут 38 секунд:
Re: Массовая вставка данных в SQLQuery, получить итоговый запрос
Поправлю себя. Похоже разбитие транзакции это фича MySQL при включенном параметре autocommit=1 при использовании движка InnoDB http://dev.mysql.com/doc/refman/5.5/en/commit.html
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Ism » 01.02.2013 01:14:09

Извиняюсь хотел упростить.
У меня myisam и компоненты zeos , в myisam вообще транзакций нет
Вообще похоже массовая вставка это фича только mysql, а компоненты сделаны чтоб работать со всеми базами
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Vadim » 01.02.2013 02:58:29

Ism
А если скрипт, как посоветовал Padre_Mortius, закидывать с помощью компонента TZSQLProcessor?
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Ism » 01.02.2013 03:09:51

Vadim писал(а):Ism
А если скрипт, как посоветовал Padre_Mortius, закидывать с помощью компонента TZSQLProcessor?

Именно, так я и делал, но это очень неудобно формировать запрос складывая запрос в строку.
Гораздо правильное присваивать через
SQLQuery.insert
FieldByName('').text:='123'
SQLQuery.Post

Но это оказывается слишком медленно , для огромных объемов. Похоже выход viewtopic.php?f=23&t=8816

TZSQLProcessor все равно выполняет SQL команды поочередно , отправляя на сервер по одной
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Padre_Mortius » 01.02.2013 09:26:43

Ism, а если отказаться от Zeos и попробовать родными компонентами Лазаря? Есть подозрение, что это специфика именно компонентов Zeos.
Padre_Mortius
энтузиаст
 
Сообщения: 1265
Зарегистрирован: 29.05.2007 17:38:07
Откуда: Спб

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Frolik » 01.02.2013 15:00:01

Единственный вариант это
insert ...
values
(1,2,3)
(6,7,8)

И так далее, если бросить такой запрос на сервер одной командой, то это будет на порядок быстрее

Просто SQLQuery не умеет бросать на сервер insert скопом, похоже придется вручную формировать


Я не понял, почему не подошел этот вариант?
Zeos прекрасно справляется с такими запросами. В моем проекте по 2-3 тысячи строк таким образом записываются. Но поля в таблице только integer.
Frolik
постоялец
 
Сообщения: 275
Зарегистрирован: 18.08.2011 11:52:32

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Vadim » 01.02.2013 18:29:32

Ism писал(а):Именно, так я и делал, но это очень неудобно формировать запрос складывая запрос в строку.

А зачем в строку?
Var
zp: TZSQLProcessor;

zp.Script.LoadFromFile()
или
For i:=1 To Кол-во_запросов Do
zp.Script.Add('INSERT ...')
а потом
zp.Execute;
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Массовая вставка данных в SQLQuery, получить итоговый за

Сообщение Ism » 01.02.2013 19:06:11

Vadim писал(а):
Ism писал(а):Именно, так я и делал, но это очень неудобно формировать запрос складывая запрос в строку.

А зачем в строку?
Var
zp: TZSQLProcessor;

zp.Script.LoadFromFile()
или
For i:=1 To Кол-во_запросов Do
zp.Script.Add('INSERT ...')
а потом
zp.Execute;

Я писал выше, ZSQLProcessor выполняет insert по одному. В случае вставки скопом достаточно ExecuteDirect, тогда строка одним пакетом отправляется на сервер и только там разбирается.Mysql гораздо быстрее разбирается с данными, чем датасет Так можно вставлять десятки тысяч строк за раз и время вставки будет в десятки раз меньше
Ism
энтузиаст
 
Сообщения: 908
Зарегистрирован: 06.04.2007 17:36:08

След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 227

Рейтинг@Mail.ru
cron