-
GanibalLector © (11.11.16 13:15) [0]Данные постоянно приходят из разных потоков и возникают дикие задержки, если их писать в цикле:
for I:=0 to TStrings(List.Items[0]).Count-1 do
begin
IBSQL1.SQL.Clear;
IBSQL1.SQL.Add('INSERT INTO ...');
...
IBSQL1.ParamByName('Поле').AsInteger:=0;
IBSQL1.ExecQuery;
end;
Хочу попробовать пакетную вставку. В связи с этим вопрос, какие варианты существуют?
Нашел следующий вариант:
execute block as begin
INSERT INTO Таблица VALUES (поля);
INSERT INTO Таблица VALUES (поля);
end
Попробовал. Не совсем удобно. IBSQL может принять только 255 строк (почему?). Еще и вместо параметров нужно указывать реальные данные, предварительно их форматируя (дату, время).
Какие еще альтернативы существуют?
Спасибо! -
Игорь Шевченко © (11.11.16 13:49) [1]
> Какие еще альтернативы существуют?
Еще существует использование параметров.
Вместоfor I:=0 to TStrings(List.Items[0]).Count-1 do
begin
IBSQL1.SQL.Clear;
IBSQL1.SQL.Add('INSERT INTO ...');
...
IBSQL1.ParamByName('Поле').AsInteger:=0;
IBSQL1.ExecQuery;
end;
написатьIBSQL1.SQL.Text := 'INSERT INTO ...';
for I:=0 to TStrings(List.Items[0]).Count-1 do
begin
...
IBSQL1.ParamByName('Поле').AsInteger:=0;
IBSQL1.ExecQuery;
end; -
iop © (11.11.16 13:50) [2]быстрый клиентский вариант один
вместо тысячи отдельных строк передать серверу один блоб, и делать инсерты по блобу на сервере.
так как сервер "не настоящий",
и там нет select from xml_type то будет нужен цикл разбора блоба и в нем инсерты.
либо искать аналог чего-то вроде мускульного через серверный файл
LOAD XML INFILE '/var/lib/mysql-files/input.xml' INTO TABLE mytable -
GanibalLector © (11.11.16 14:13) [3]
> быстрый клиентский вариант один
> вместо тысячи отдельных строк передать серверу один блоб,
> и делать инсерты по блобу на сервере.
>
> так как сервер "не настоящий",
> и там нет select from xml_type то будет нужен цикл разбора
> блоба и в нем инсерты.
Где бы найти пример подобной реализации? Вы сами подобное реализовывали или это теория? -
iop © (11.11.16 14:41) [4]вся "теория" это работа с текстовым блобом на сервере.
сейчас тормозит потому что много инсертов с клиента.
будет один запрос с блобом с клиента и много инсертов на сервере - будет быстро в разы разов. -
GanibalLector © (11.11.16 14:52) [5]
> вся "теория" это работа с текстовым блобом на сервере.
Текстовый блоб это простой текстовый файл с разделителями?
В хранимую процедуру я передаю этот файл (путь), а дальше его разбираю и выполняю. Так? -
iop © (11.11.16 14:57) [6]в хранимую процедуру параметром передается тело файла, а не путь к файлу.
-
ухты_х © (11.11.16 15:29) [7]
> Где бы найти пример подобной реализации? Вы сами подобное
> реализовывали или это теория?
тут что то похожее http://www.ibase.ru/xmldb/ -
GanibalLector © (11.11.16 13:15)
Странно СУБД на то и СУБД чтобы "разруливать" эти ситуации... -
Вариант (12.11.16 07:52) [9]
> GanibalLector © (11.11.16 13:15)
Еще варианты:
1 - Группировка данных и вставка группы одной транзакцией. Например по накоплению N записей или истечению тайм-аута, если за заданный интервал не накопил нужное число записей. (пробовал сам такой вариант, ускоряет в разы.)
2 - Создание пула потоков, которые работают с БД. Запросы делятся между потоками. У меня так сейчас работает порядка 15000 "клиентов" с одним сервером. У каждого потока своя очередь запросов. -
Inovet © (12.11.16 11:48) [10]Вы тут какие-то пулы советуете, а автору надо хотя бы базовые вещи грамотно сделать. ИШ уже сказал в
> [1] Игорь Шевченко © (11.11.16 13:49)
Можно добавить ещё перед циклом
IBSQL1.Prepare
и после цикла, если надо
IBSQL1.Unprepare
до следующего раза. Почитать в общем о параметрах надо.