Есть такая проблема: имеется recordset (ADO), полученный путем загрузки из .XML файла. Надо данные из него закачать в базу. Сейчас я делаю так: прохожу по всему recordsetу, создаю строку запроса типа INSERT INTO TableName(Field1, Field2) VALUES(1, 2) и кидаю на сервер. Все работает, но исключительно медленно. Есть какой-либо быстрый способ закачки данных?
Здравствуйте stan1, Вы писали:
S>Есть такая проблема: имеется recordset (ADO), полученный путем загрузки из .XML файла. Надо данные из него закачать в базу. Сейчас я делаю так: прохожу по всему recordsetу, создаю строку запроса типа INSERT INTO TableName(Field1, Field2) VALUES(1, 2) и кидаю на сервер. Все работает, но исключительно медленно. Есть какой-либо быстрый способ закачки данных?
Ну, первое, что приходит на ум, это поместить такой INSERT-запрос в параметризованный запрос для ADODB.Command и в цикле долько обновлять значения связанных переменных переменных:
INSERT INTO TableName(Field1, Field2) VALUES(@val1, @val2);
Тогда экономится время на парсинг sql в каждой итерации.
А если хочется большего, то рекордсет можно присоединить к ActiveConnection после загрузки из XML и вызвать у него UpdateBatch. Но это пройдет не для всех рекордсетов и провайдеров.
Мой совет может и глупый но его скорострельность быстрее, чем insert для каждой строки , проверено...
Открой пустой RS из таблицы в которую будешь добавлять... Потом в цикле через AddNew тупо подобавляй в этот RS все строки и сделай UpdateBatch(adAffectAll).
Если не жалко — кинь мне, пожалуйста, на мыло alex2808@mail.ru кусок своего кода и пример XML файла, где переганяешь с XML в RS и наоборот, где формируешь XML файл. Давно интересует меня эта тема, передача данных с пом. XML, да все за гонкой руки не доходят присмотреться. А интересно... Please.
Попробовал сделать так: rs->Open("filename.xml",.....); rs->ActiveConnection = cnn; rs->UpdateBatch(adAffectAll);
Записи в таблице не появляются. Насколько я понимаю, recordset считает, что изменений не было, и ничего не делает. Как можно объявить записи инвалидными, чтобы UpdateBatch их сбросил?
Не хочется Вас огорчать, но похоже, что UpdateBatch работает медленнее command->Execute. Вот результаты: INSERT 1000 записей в таблицу через command->Execute выполняется за 6 секунд, а спомощью UpdateBatch за 8 секунд. И то и другое жутко медленно. Нет ли еще каких идей? На всякий случай, кусок кода, использованного при тестировании:
// Using UpdateBatch
ora_cnn->Open("Provider=MSDAORA.1;Data Source=base1;UserID=login;Password=pwd;","","",-1);
time_t tt, tt1;
time(&tt);
char buf[100];
ora_rs->CursorLocation = ADODB::adUseClient;
ora_rs->Open("select * from SS_MIGRATION_LOGS where 1=2",
_variant_t((IDispatch *)ora_cnn,true),
ADODB::adOpenStatic,
ADODB::adLockBatchOptimistic,
ADODB::adCmdText);
_variant_t var((IDispatch *) NULL,false);
var.ChangeType(VT_DISPATCH);
ora_rs->PutActiveConnection ( var );
Попробовал твой пример, но не с Oracle а с Access.
1000 записей оба добавляют за 2 сек. (Р3-866, 256 Mb)
Расширил до 20000 записей. AddNew — 42 сек., Insert — 43 сек.
Разница не большая, но приятно Так что здесь я обшибси насчет скорости, у меня по задаче просто визуализация в ГРИД идет при добавлении, и при INSERT приходилось обновлять RS.
Попробуй stored процедуру, если планируешь работать только с Ораклом. Или Pro C процедурку сделай, там за счет коннекта хороший выиграш идет.
PS: А я сейчас с транзакциями в ADO воюю
Здравствуйте stan1, Вы писали:
S>Не хочется Вас огорчать, но похоже, что UpdateBatch работает медленнее command->Execute. Вот результаты: INSERT 1000 записей в таблицу через command->Execute выполняется за 6 секунд, а спомощью UpdateBatch за 8 секунд. И то и другое жутко медленно. Нет ли еще каких идей? На всякий случай, кусок кода, использованного при тестировании:
Примеры лучше обрамляй сишными тэгами, иначе не читается.
При таком подходе у тебя 1000 раз БД выполняет синтаксический разбор твоего INSERT'а. Я же говорю, заведи ADODB.Command и добавь изменяемое значение в его коллекцию Parameters.
Драматического ускорения не получишь, но получше точно будет (зависит от многого).
Здравствуйте retalik, Вы писали:
R>Ну, первое, что приходит на ум, это поместить такой INSERT-запрос в параметризованный запрос для ADODB.Command и в цикле долько обновлять значения связанных переменных переменных: R>INSERT INTO TableName(Field1, Field2) VALUES(@val1, @val2);
2Retalik: Можно небольшой примерчик в цикле, мне интересно, как значения менять val1, val2. Что-то примера найти не могу...
Здравствуйте alex2808, Вы писали:
A>Здравствуйте retalik, Вы писали:
R>>Ну, первое, что приходит на ум, это поместить такой INSERT-запрос в параметризованный запрос для ADODB.Command и в цикле долько обновлять значения связанных переменных переменных: R>>INSERT INTO TableName(Field1, Field2) VALUES(@val1, @val2);
A>2Retalik: Можно небольшой примерчик в цикле, мне интересно, как значения менять val1, val2. Что-то примера найти не могу...
Ничего, что на JScript? Зато пример рабочий:
// c - это ADODB.Connection
c.Open("Provider=MSDAORA; Data Source="+select1.value, userid.value, password.value);
var cmd=new ActiveXObject("ADODB.Command");
cmd.ActiveConnection=c;
cmd.CommandType=adCmdText;
cmd.CommandText="{call budget_pack.updateParameter(budget_pack.READ#, '2001', 'plan_sign', ?, ?)}";
v=cmd.CreateParameter("@v",adInteger,adInOut,10,0);
t=cmd.CreateParameter("@t",adVarChar,adInOut,2000,"");
cmd.Parameters.Append(v);
cmd.Parameters.Append(t);
cmd.Execute();
plan_sign=cmd.Parameters("@v").Value;
Необходимые замечания.
1. Это было довольно давно, ADO 2.0 и Oracle 7.3. Тогда у Оракла не было нормального провайдера для OLE DB, и приходилось использовать такой зверский синтаксис с adCmdText и "{call..?,?.}". Сейчас, как люди говорят, можно
использовать adCmdStoredProc, как и везде.
2. После того, как параметры добавлены в коллекцию, их значения меняются там же, а затем вновь вызывается Execute.
Здравствуйте stan1, Вы писали:
S>Есть такая проблема: имеется recordset (ADO), полученный путем загрузки из .XML файла. Надо данные из него закачать в базу. Сейчас я делаю так: прохожу по всему recordsetу, создаю строку запроса типа INSERT INTO TableName(Field1, Field2) VALUES(1, 2) и кидаю на сервер. Все работает, но исключительно медленно. Есть какой-либо быстрый способ закачки данных?