insert из recordseta (ADO)
От: stan1  
Дата: 21.02.02 10:36
Оценка:
Есть такая проблема: имеется recordset (ADO), полученный путем загрузки из .XML файла. Надо данные из него закачать в базу. Сейчас я делаю так: прохожу по всему recordsetу, создаю строку запроса типа INSERT INTO TableName(Field1, Field2) VALUES(1, 2) и кидаю на сервер. Все работает, но исключительно медленно. Есть какой-либо быстрый способ закачки данных?
Re: insert из recordseta (ADO)
От: retalik www.airbandits.com/
Дата: 21.02.02 10:46
Оценка:
Здравствуйте 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. Но это пройдет не для всех рекордсетов и провайдеров.
Успехов,
Виталий.
Re: insert из recordseta (ADO)
От: alex2808 Украина  
Дата: 22.02.02 12:04
Оценка:
Мой совет может и глупый но его скорострельность быстрее, чем insert для каждой строки , проверено...
Открой пустой RS из таблицы в которую будешь добавлять... Потом в цикле через AddNew тупо подобавляй в этот RS все строки и сделай UpdateBatch(adAffectAll).

Если не жалко — кинь мне, пожалуйста, на мыло alex2808@mail.ru кусок своего кода и пример XML файла, где переганяешь с XML в RS и наоборот, где формируешь XML файл. Давно интересует меня эта тема, передача данных с пом. XML, да все за гонкой руки не доходят присмотреться. А интересно... Please.
Всех благ
Re[2]: insert из recordseta (ADO)
От: stan1  
Дата: 22.02.02 13:21
Оценка:
Попробовал сделать так:
rs->Open("filename.xml",.....);
rs->ActiveConnection = cnn;
rs->UpdateBatch(adAffectAll);
Записи в таблице не появляются. Насколько я понимаю, recordset считает, что изменений не было, и ничего не делает. Как можно объявить записи инвалидными, чтобы UpdateBatch их сбросил?
Re[2]: insert из recordseta (ADO)
От: stan1  
Дата: 25.02.02 17:08
Оценка:
Не хочется Вас огорчать, но похоже, что 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 );

for(int i=0;i<1000;i++){
ora_rs->AddNew();
ora_rs->Fields->GetItem(_bstr_t("VC_CHAPTER"))->Value = _bstr_t(itoa(i, buf, 10));
}
ora_rs->PutActiveConnection ( _variant_t((IDispatch *) ora_cnn,true ) );
ora_rs->UpdateBatch(ADODB::adAffectAll);
time(&tt1);
cout<<tt1 — tt;



// Using Execute
for(int i=0;i<1000;i++){
ora_cnn->Execute(_bstr_t("INSERT INTO SS_MIGRATION_LOGS(VC_CHAPTER) VALUES('") + itoa(i, buf, 10) + "')",
0,
ADODB::adExecuteNoRecords);
}
time(&tt1);
cout<<tt1 — tt;
Re: insert из recordseta (ADO)
От: alex2808 Украина  
Дата: 26.02.02 10:23
Оценка:
Попробовал твой пример, но не с Oracle а с Access.
1000 записей оба добавляют за 2 сек. (Р3-866, 256 Mb)
Расширил до 20000 записей. AddNew — 42 сек., Insert — 43 сек.
Разница не большая, но приятно Так что здесь я обшибси насчет скорости, у меня по задаче просто визуализация в ГРИД идет при добавлении, и при INSERT приходилось обновлять RS.
Попробуй stored процедуру, если планируешь работать только с Ораклом. Или Pro C процедурку сделай, там за счет коннекта хороший выиграш идет.
PS: А я сейчас с транзакциями в ADO воюю
Всех благ
Re[3]: insert из recordseta (ADO)
От: retalik www.airbandits.com/
Дата: 26.02.02 13:02
Оценка:
Здравствуйте stan1, Вы писали:

S>Не хочется Вас огорчать, но похоже, что UpdateBatch работает медленнее command->Execute. Вот результаты: INSERT 1000 записей в таблицу через command->Execute выполняется за 6 секунд, а спомощью UpdateBatch за 8 секунд. И то и другое жутко медленно. Нет ли еще каких идей? На всякий случай, кусок кода, использованного при тестировании:


Примеры лучше обрамляй сишными тэгами, иначе не читается.
S>// Using Execute
S>    for(int i=0;i<1000;i++){
S>    ora_cnn->Execute(_bstr_t("INSERT INTO SS_MIGRATION_LOGS(VC_CHAPTER) VALUES('") + itoa(i, buf, 10) + "')", 
S>                            0, 
S>                            ADODB::adExecuteNoRecords);
S>    }
S>    time(&tt1);
S>    cout<<tt1 - tt;


При таком подходе у тебя 1000 раз БД выполняет синтаксический разбор твоего INSERT'а. Я же говорю, заведи ADODB.Command и добавь изменяемое значение в его коллекцию Parameters.
Драматического ускорения не получишь, но получше точно будет (зависит от многого).
Успехов,
Виталий.
Re[2]: insert из recordseta (ADO)
От: alex2808 Украина  
Дата: 01.03.02 13:39
Оценка:
Здравствуйте retalik, Вы писали:

R>Ну, первое, что приходит на ум, это поместить такой INSERT-запрос в параметризованный запрос для ADODB.Command и в цикле долько обновлять значения связанных переменных переменных:

R>INSERT INTO TableName(Field1, Field2) VALUES(@val1, @val2);

2Retalik: Можно небольшой примерчик в цикле, мне интересно, как значения менять val1, val2. Что-то примера найти не могу...
Всех благ
Re[3]: insert из recordseta (ADO)
От: retalik www.airbandits.com/
Дата: 01.03.02 14:11
Оценка:
Здравствуйте 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.
for(i=1;i<1000;i++)
{
    cmd.Parameters("@v").Value=i;
    cmd.Execute();
}
Успехов,
Виталий.
Re: insert из recordseta (ADO)
От: Delirium  
Дата: 02.03.02 13:49
Оценка:
Здравствуйте stan1, Вы писали:

S>Есть такая проблема: имеется recordset (ADO), полученный путем загрузки из .XML файла. Надо данные из него закачать в базу. Сейчас я делаю так: прохожу по всему recordsetу, создаю строку запроса типа INSERT INTO TableName(Field1, Field2) VALUES(1, 2) и кидаю на сервер. Все работает, но исключительно медленно. Есть какой-либо быстрый способ закачки данных?



У самого MSSQL есть конструкция — OPENXML
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.