Массовая вставка данных в SQLQuery, получить итоговый запрос
Модератор: Модераторы
Массовая вставка данных в SQLQuery, получить итоговый запрос
Привет
Необходимо вставить сразу более 20000 записей. Но вот проблема, SQLQuery в режиме CachedUpdates:=true по ApplyUpdates применяет вставку по одному insert, что гораздо медленнее , чем просто бросить скрипт вставки на сервер и там выполнить
Сервер MySql
Есть ли возможность получить скрипт вставки из DataSet не отправляя данные, а потом отправить на сервер через ExecuteDirect ?
Можно конечно сформировать запрос вручную, но это неудобно
Необходимо вставить сразу более 20000 записей. Но вот проблема, SQLQuery в режиме CachedUpdates:=true по ApplyUpdates применяет вставку по одному insert, что гораздо медленнее , чем просто бросить скрипт вставки на сервер и там выполнить
Сервер MySql
Есть ли возможность получить скрипт вставки из DataSet не отправляя данные, а потом отправить на сервер через ExecuteDirect ?
Можно конечно сформировать запрос вручную, но это неудобно
-
Padre_Mortius
- энтузиаст
- Сообщения: 1265
- Зарегистрирован: 29.05.2007 17:38:07
- Откуда: Спб
данные вы откуда берете?
если из таблицы. то вроде была возможность использовать что-то вроде
если из таблицы. то вроде была возможность использовать что-то вроде
Код: Выделить всё
insert into table select * from table2 where ...Padre_Mortius писал(а):данные вы откуда берете?
если из таблицы. то вроде была возможность использовать что-то вродеКод: Выделить всё
insert into table select * from table2 where ...
Тут все проблематично, данные берутся из одной базы(не MySql) и сливаются в другую, поэтому единственный вариант брать запись из одной базы и бросать в другую.
Ускорить можно только бросая пакетами, и как заставить SQLQuery это делать непонятно
-
Padre_Mortius
- энтузиаст
- Сообщения: 1265
- Зарегистрирован: 29.05.2007 17:38:07
- Откуда: Спб
Можно попробовать несколько Insert-запросов обрамить в
Я делал похожим образом для sqlite, но там пользовался их API, а не SQLQuery (причину уже не помню)
Код: Выделить всё
BEGIN TRANSACTION;
INSERT ...;
INSERT ...;
COMMIT TRANSACTION;Я делал похожим образом для sqlite, но там пользовался их API, а не SQLQuery (причину уже не помню)
Padre_Mortius писал(а):Можно попробовать несколько Insert-запросов обрамить вКод: Выделить всё
BEGIN TRANSACTION;
INSERT ...;
INSERT ...;
COMMIT TRANSACTION;
Я делал похожим образом для sqlite, но там пользовался их API, а не SQLQuery (причину уже не помню)
В этом проблемы нет, проблема в том, что один insert на строку даже в транзакции медленно передается и выполняется,
Единственный вариант это
insert ...
values
(1,2,3)
(6,7,8)
И так далее, если бросить такой запрос на сервер одной командой, то это будет на порядок быстрее
Просто SQLQuery не умеет бросать на сервер insert скопом, похоже придется вручную формировать
-
Padre_Mortius
- энтузиаст
- Сообщения: 1265
- Зарегистрирован: 29.05.2007 17:38:07
- Откуда: Спб
Если к TSQLQuery подключен TTransactionSQL, то должно очень быстро выполняться...
Padre_Mortius писал(а):Если к TSQLQuery подключен TTransactionSQL, то должно очень быстро выполняться...
Дело не в транзакции, а в том, что по одному insert медленнее, чем вариант указанный выше
-
Padre_Mortius
- энтузиаст
- Сообщения: 1265
- Зарегистрирован: 29.05.2007 17:38:07
- Откуда: Спб
Разве при оформлении в явную транзакцию сервер должен ее разбивать эту транзакцию на более мелкие коммиты? К транзакции вроде должен применяться только один коммит в конце если нет ошибок, или rollback если произошла ошибка. И параметра CachedUpdates у TSQLQuery не нашел (Лазарь 1.1 из свн)
Добавлено спустя 5 минут 38 секунд:
Re: Массовая вставка данных в SQLQuery, получить итоговый запрос
Поправлю себя. Похоже разбитие транзакции это фича MySQL при включенном параметре autocommit=1 при использовании движка InnoDB http://dev.mysql.com/doc/refman/5.5/en/commit.html
Добавлено спустя 5 минут 38 секунд:
Re: Массовая вставка данных в SQLQuery, получить итоговый запрос
Поправлю себя. Похоже разбитие транзакции это фича MySQL при включенном параметре autocommit=1 при использовании движка InnoDB http://dev.mysql.com/doc/refman/5.5/en/commit.html
Извиняюсь хотел упростить.
У меня myisam и компоненты zeos , в myisam вообще транзакций нет
Вообще похоже массовая вставка это фича только mysql, а компоненты сделаны чтоб работать со всеми базами
У меня myisam и компоненты zeos , в myisam вообще транзакций нет
Вообще похоже массовая вставка это фича только mysql, а компоненты сделаны чтоб работать со всеми базами
Ism
А если скрипт, как посоветовал Padre_Mortius, закидывать с помощью компонента TZSQLProcessor?
А если скрипт, как посоветовал Padre_Mortius, закидывать с помощью компонента TZSQLProcessor?
Vadim писал(а):Ism
А если скрипт, как посоветовал Padre_Mortius, закидывать с помощью компонента TZSQLProcessor?
Именно, так я и делал, но это очень неудобно формировать запрос складывая запрос в строку.
Гораздо правильное присваивать через
SQLQuery.insert
FieldByName('').text:='123'
SQLQuery.Post
Но это оказывается слишком медленно , для огромных объемов. Похоже выход viewtopic.php?f=23&t=8816
TZSQLProcessor все равно выполняет SQL команды поочередно , отправляя на сервер по одной
-
Padre_Mortius
- энтузиаст
- Сообщения: 1265
- Зарегистрирован: 29.05.2007 17:38:07
- Откуда: Спб
Ism, а если отказаться от Zeos и попробовать родными компонентами Лазаря? Есть подозрение, что это специфика именно компонентов Zeos.
Единственный вариант это
insert ...
values
(1,2,3)
(6,7,8)
И так далее, если бросить такой запрос на сервер одной командой, то это будет на порядок быстрее
Просто SQLQuery не умеет бросать на сервер insert скопом, похоже придется вручную формировать
Я не понял, почему не подошел этот вариант?
Zeos прекрасно справляется с такими запросами. В моем проекте по 2-3 тысячи строк таким образом записываются. Но поля в таблице только integer.
Ism писал(а):Именно, так я и делал, но это очень неудобно формировать запрос складывая запрос в строку.
А зачем в строку?
Var
zp: TZSQLProcessor;
zp.Script.LoadFromFile()
или
For i:=1 To Кол-во_запросов Do
zp.Script.Add('INSERT ...')
а потом
zp.Execute;
Vadim писал(а):Ism писал(а):Именно, так я и делал, но это очень неудобно формировать запрос складывая запрос в строку.
А зачем в строку?
Var
zp: TZSQLProcessor;
zp.Script.LoadFromFile()
или
For i:=1 To Кол-во_запросов Do
zp.Script.Add('INSERT ...')
а потом
zp.Execute;
Я писал выше, ZSQLProcessor выполняет insert по одному. В случае вставки скопом достаточно ExecuteDirect, тогда строка одним пакетом отправляется на сервер и только там разбирается.Mysql гораздо быстрее разбирается с данными, чем датасет Так можно вставлять десятки тысяч строк за раз и время вставки будет в десятки раз меньше
