Конференция "Базы" » ADO+ClientDataSet+TThread [D7, Access]
 
  • Alex_C (16.11.11 14:13) [0]
    Чем дальше в лес, тем задачи усложняются.
    Теперь есть такая проблема: получаю из инета пакет около 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 клал просто на форму - все работало.
  • Медвежонок Пятачок © (16.11.11 14:29) [1]
    Если вставлять каждую запись через ADODataSet - естественно получается очень долго. По этому я так понимаю нужно использовать ClientDataSet.

    .... который сам по себе не умеет ничего и никуда вставлять, а действует через посердников. Так откуда вдруг возьмется быстрота?
  • Медвежонок Пятачок © (16.11.11 14:31) [2]
    //ADODataSet1.CommandText := 'SELECT * FROM SpotTable';
    AdoCommand.CommandText := 'insert into SpotTable() values()';
  • Alex_C (16.11.11 14:45) [3]

    > AdoCommand.CommandText := 'insert into SpotTable() values()';


    Я именно так и вставлял.
    Приведенный пример - из пробной программы. Я пытался подсоединиться к ADODataSet при Runtime создании ClientDataSet.
  • Медвежонок Пятачок © (16.11.11 14:46) [4]
    Ну и кроме того, провайдер в рантайме устанавливается не через свойство, а через метод.
  • Медвежонок Пятачок © (16.11.11 14:47) [5]
    Я именно так и вставлял.

    а это зачем здесь написал:
    ADODataSet1.CommandText := 'SELECT * FROM SpotTable';
  • Alex_C (16.11.11 14:47) [6]
    Еще поясню: вообще мне эти полученные данные нужно по хорошему все время работы программы в памяти держать, только при завершении работы записывать их в таблицу.
  • Alex_C (16.11.11 14:48) [7]

    > ADODataSet1.CommandText := 'SELECT * FROM SpotTable';


    Это пробовал вообще связка ADO+ClientDataSet работает или нет. Если ClientDataSet на форму класть - работает. Сздавать в рантайм - нет.
  • Медвежонок Пятачок © (16.11.11 14:49) [8]
    Но логика просто вне границ постижимого.

    "Датасет вставляет медленно, значит прикрутим к нему клиентдатасет. Датасет после этого испугается и начнет вставлять на форсаже".
  • Alex_C (16.11.11 14:55) [9]
    Для начала о проблеме - в рантайме при создании ClientDataSet нужно использовать CreateDataSet.


    > Датасет вставляет медленно


    Датасает вставляет данные в таблицу, которая имеет объем мегабайты.


    > клиентдатасет


    Клиентвет - никуда ничено не вставляет. Все содержит в памяти, а к базе обращается когда ему скажешь ApplyUpdate.
    Вот от  куда скорость :)
  • Медвежонок Пятачок © (16.11.11 14:58) [10]
    а к базе обращается когда ему скажешь ApplyUpdate.
    Вот от  куда скорость :)


    Открою тайну.
    Там нет никакой сверх скорости.
    Просто там нет сверх-тормозов, которые есть в твоем алгоритме вставки.

    А так этот аплайапдейт точно также вставляет строку за строкой отдельными инсертами.
  • MsGuns © (16.11.11 15:02) [11]
    >Alex_C   (16.11.11 14:55) [9]
    >Для начала о проблеме - в рантайме при создании ClientDataSet нужно >использовать CreateDataSet.

    Вы по ходу путаете создание экземпляра TClientDataSet и собственно датасета, как "хранилища" данных.
  • MsGuns © (16.11.11 15:06) [12]
    И согласен с медвежонком,- используете TClientDataSet явно не по назначению (для временного хранения табличных данных, например в течение сеанса, обычно используют временные локальные таблицы на сервере, а  память используют для хранилища только в том случае, если "базы вообще нет "под рукой" либо обмен с нею затруднителен (медленный, с обрывами  и т.д.) Ну или в сервере приложений.
  • Inovet © (16.11.11 15:14) [13]
    > [6] Alex_C   (16.11.11 14:47)
    > Еще поясню: вообще мне эти полученные данные нужно по хорошему
    > все время работы программы в памяти держать, только при
    > завершении работы записывать их в таблицу.

    Если их всё равно надо записать, то надо это сджелать как можно быстрее, т.е. сразу при получении. В памяти они и так в Dataset хранятся.


    > [9] Alex_C   (16.11.11 14:55)
    > Датасает вставляет данные в таблицу, которая имеет объем мегабайты.

    Это мелочь.

    Я тебе уже говорил - в запросах желательно пользоваться параметрами.
  • Alex_C (16.11.11 15:15) [14]

    > CreateDataSet


    SetProvider нужно делать при подключении к новому провайдеру - эта проблема решена.


    > TClientDataSet явно не по назначению


    Сейчас второй час читаю статьи из инета, где везда сказано, что вот как раз для этой цели необходимо использовать TClientDataSet . И везде именно делается акцент на то, что TClientDataSet все делает в памяти.
  • Alex_C (16.11.11 15:19) [15]
    Вот процедура, которой я вставляю данные в таблицу


    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.
  • Медвежонок Пятачок © (16.11.11 15:19) [16]
    что вот как раз для этой цели необходимо использовать TClientDataSet

    Для какой "этой" цели?
  • Медвежонок Пятачок © (16.11.11 15:28) [17]
    with SpotDataSet do
    begin
      CommandText := 'INSERT INTO SpotTable (DXCall,DateSpot,TimeSpot,Freq,' +
        'SpoterCall,Info,DateTimeOfGet,IsNewCountry,IsNewSpot,Country,BandADIF,Mode) '


    Львиная доля времени из всех 5-8 секунд здесь уходит на перечитывание метаданных и строительство списка переметров.
    Что у проф программиста отсутствует.
  • Медвежонок Пятачок © (16.11.11 15:29) [18]
    .... И делается это тупое бесполезное дело все двести пятьдесят раз.
  • Alex_C (16.11.11 15:29) [19]
    В общем вы все конечно правы :)
    Не поленился, сделал все с ClientDataSet - скорость точно такая же, как и с одним ADOCommand - скорость вставки ничем не отличается.


    > Для какой "этой" цели?


    Цель - создание временной, максимально быстрой таблицы в памяти, количество записей - менее 500. Нужна максимально быстрая вставка и выборка. Вставка производится из нескольких потоков (т.е. таблица должна быть потокозащищенной).
    Вот как то так))
 
Конференция "Базы" » ADO+ClientDataSet+TThread [D7, Access]
Есть новые Нет новых   [134431   +10][b:0][p:0.002]