-
Чем дальше в лес, тем задачи усложняются. Теперь есть такая проблема: получаю из инета пакет около 250 записей. Их надо в отдельном треде получить, обработать и вставить в таблицу. Если вставлять каждую запись через ADODataSet - естественно получается очень долго. По этому я так понимаю нужно использовать ClientDataSet. Однако появился вопрос при использовании всей этой связки в отдельном треде: когда я пробовал напрямую данные в ADODataSet вставлять, я для каждого треда создавал свой ADOConnectin+ADODataSet в соответствии с рекомендациями. Если пытаться создавать еще и TDataSetProvider и TClientDataSet
ADODataSet1.Active := False;
ADODataSet1.CommandText := 'SELECT * FROM SpotTable';
ADODataSet1.Active := True;
FSpotDataSetProvider := TDataSetProvider.Create(nil);
FSpotDataSetProvider.DataSet := ADODataSet1;
FSpotClientDataSet := TClientDataSet.Create(nil);
FSpotClientDataSet.ProviderName := 'FSpotDataSetProvider';
FSpotClientDataSet.Open;
на FSpotClientDataSet.Open; выходит сообщение 'Missing data provider or data packet'. Хотя когда делал пробное приложение и TDataSetProvider и TClientDataSet клал просто на форму - все работало.
-
Если вставлять каждую запись через ADODataSet - естественно получается очень долго. По этому я так понимаю нужно использовать ClientDataSet.
.... который сам по себе не умеет ничего и никуда вставлять, а действует через посердников. Так откуда вдруг возьмется быстрота?
-
//ADODataSet1.CommandText := 'SELECT * FROM SpotTable'; AdoCommand.CommandText := 'insert into SpotTable() values()';
-
> AdoCommand.CommandText := 'insert into SpotTable() values()';
Я именно так и вставлял. Приведенный пример - из пробной программы. Я пытался подсоединиться к ADODataSet при Runtime создании ClientDataSet.
-
Ну и кроме того, провайдер в рантайме устанавливается не через свойство, а через метод.
-
Я именно так и вставлял.
а это зачем здесь написал: ADODataSet1.CommandText := 'SELECT * FROM SpotTable';
-
Еще поясню: вообще мне эти полученные данные нужно по хорошему все время работы программы в памяти держать, только при завершении работы записывать их в таблицу.
-
> ADODataSet1.CommandText := 'SELECT * FROM SpotTable';
Это пробовал вообще связка ADO+ClientDataSet работает или нет. Если ClientDataSet на форму класть - работает. Сздавать в рантайм - нет.
-
Но логика просто вне границ постижимого.
"Датасет вставляет медленно, значит прикрутим к нему клиентдатасет. Датасет после этого испугается и начнет вставлять на форсаже".
-
Для начала о проблеме - в рантайме при создании ClientDataSet нужно использовать CreateDataSet.
> Датасет вставляет медленно
Датасает вставляет данные в таблицу, которая имеет объем мегабайты.
> клиентдатасет
Клиентвет - никуда ничено не вставляет. Все содержит в памяти, а к базе обращается когда ему скажешь ApplyUpdate. Вот от куда скорость :)
-
а к базе обращается когда ему скажешь ApplyUpdate. Вот от куда скорость :)
Открою тайну. Там нет никакой сверх скорости. Просто там нет сверх-тормозов, которые есть в твоем алгоритме вставки.
А так этот аплайапдейт точно также вставляет строку за строкой отдельными инсертами.
-
>Alex_C (16.11.11 14:55) [9] >Для начала о проблеме - в рантайме при создании ClientDataSet нужно >использовать CreateDataSet.
Вы по ходу путаете создание экземпляра TClientDataSet и собственно датасета, как "хранилища" данных.
-
И согласен с медвежонком,- используете TClientDataSet явно не по назначению (для временного хранения табличных данных, например в течение сеанса, обычно используют временные локальные таблицы на сервере, а память используют для хранилища только в том случае, если "базы вообще нет "под рукой" либо обмен с нею затруднителен (медленный, с обрывами и т.д.) Ну или в сервере приложений.
-
> [6] Alex_C (16.11.11 14:47) > Еще поясню: вообще мне эти полученные данные нужно по хорошему > все время работы программы в памяти держать, только при > завершении работы записывать их в таблицу.
Если их всё равно надо записать, то надо это сджелать как можно быстрее, т.е. сразу при получении. В памяти они и так в Dataset хранятся.
> [9] Alex_C (16.11.11 14:55) > Датасает вставляет данные в таблицу, которая имеет объем мегабайты.
Это мелочь.
Я тебе уже говорил - в запросах желательно пользоваться параметрами.
-
> CreateDataSet
SetProvider нужно делать при подключении к новому провайдеру - эта проблема решена.
> TClientDataSet явно не по назначению
Сейчас второй час читаю статьи из инета, где везда сказано, что вот как раз для этой цели необходимо использовать TClientDataSet . И везде именно делается акцент на то, что TClientDataSet все делает в памяти.
-
Вот процедура, которой я вставляю данные в таблицу
procedure InsertSpot(SpotDataSet: TADODataSet;
DXCall: string; DateSpot, TimeSpot: TDateTime;
Freq: Double; SpoterCall, Info: string; DateTimeOfGet: TDateTime;
IsNewCountry: integer; IsNewSpot: Boolean; Country, BandADIF, Mode: string);
begin
with SpotDataSet do
begin
CommandText := 'INSERT INTO SpotTable (DXCall,DateSpot,TimeSpot,Freq,' +
'SpoterCall,Info,DateTimeOfGet,IsNewCountry,IsNewSpot,Country,BandADIF,Mode) ' +
'VALUES(:DXCall,:DateSpot,:TimeSpot,:Freq,:SpoterCall,:Info,:DateTimeOfGet,' +
':IsNewCountry,:IsNewSpot,:Country,:BandADIF,:Mode)';
Parameters.ParamByName('DXCall').Value := DXCall;
Parameters.ParamByName('DateSpot').Value := DateSpot;
Parameters.ParamByName('TimeSpot').Value := TimeSpot;
Parameters.ParamByName('Freq').Value := Freq;
Parameters.ParamByName('SpoterCall').Value := SpoterCall;
Parameters.ParamByName('Info').Value := Info;
Parameters.ParamByName('DateTimeOfGet').Value := DateTimeOfGet;
Parameters.ParamByName('IsNewCountry').Value := IsNewCountry;
Parameters.ParamByName('IsNewSpot').Value := IsNewSpot;
Parameters.ParamByName('Country').Value := Country;
Parameters.ParamByName('BandADIF').Value := BandADIF;
Parameters.ParamByName('Mode').Value := Mode;
Execute;
end;
end; На вставку 250 записей уходит порядка 5-8 сек. У знакомого, проф программиста, использующего практически все тоже самое, все вставляется мгновенно. Спросил почему? Ответ был ClientDataSet. Опять же - читаю что в инете пишут. Все тоже - использовать ClientDataSet.
-
что вот как раз для этой цели необходимо использовать TClientDataSet
Для какой "этой" цели?
-
with SpotDataSet do begin CommandText := 'INSERT INTO SpotTable (DXCall,DateSpot,TimeSpot,Freq,' + 'SpoterCall,Info,DateTimeOfGet,IsNewCountry,IsNewSpot,Country,BandADIF,Mode) '
Львиная доля времени из всех 5-8 секунд здесь уходит на перечитывание метаданных и строительство списка переметров. Что у проф программиста отсутствует.
-
.... И делается это тупое бесполезное дело все двести пятьдесят раз.
-
В общем вы все конечно правы :) Не поленился, сделал все с ClientDataSet - скорость точно такая же, как и с одним ADOCommand - скорость вставки ничем не отличается.
> Для какой "этой" цели?
Цель - создание временной, максимально быстрой таблицы в памяти, количество записей - менее 500. Нужна максимально быстрая вставка и выборка. Вставка производится из нескольких потоков (т.е. таблица должна быть потокозащищенной). Вот как то так))
|