Добрый день. только начал разбираться с базами данных и возникли сложности при обработке больших объемов.
в таблице есть записи, некоторые числовые данные за несколько минутный интервал. поля TimeFrom и TimeTo есть соответственно, по которым ясен интервал.
Нужно собрать таблицу почасовых данных. где каждая запись - сумма данных за 1 час.
c:=chr(39);
FDQueryL[0].DisableControls; DBGridL0.DataSource.DataSet.DisableControls;
DBGridL0.Visible:=false;
idR:=0;
d:=EncodeDate(2017,1,1)+EncodeTime(1,0,0,0); d1:=d;
while d<now do
begin
//for line := 4 to 20 do
begin
//выбитаем все что в 1 часе
FDQueryL[0].Open('SELECT * FROM '+valL0.Values['Table']+' '+
'WHERE ID_CL='+inttostr(line)+' AND '+
'TimeFrom BETWEEN '+
c+FormatDateTime('yyyy-mm-dd h:mm:ss', d)+c+
' AND '+
c+FormatDateTime('yyyy-mm-dd h:mm:ss', IncSecond(d, 3599))+c+';');
//считаем сумму минут
m:=0; InA:=0; InC:=0; OutA:=0; OutC:=0;
DBGridL0.DataSource.DataSet.First;
while (not DBGridL0.DataSource.DataSet.Eof) do
begin
m:=m+SecondOfTheDay(DBGridL0.DataSource.DataSet.Fields[2].AsDateTime)-SecondOfTheDay(DBGridL0.DataSource.DataSet.Fields[1].AsDateTime);
//суммирование непосредственно нужных данных
InA:=InA + DBGridL0.DataSource.DataSet.Fields[4].AsInteger;
InC:=InC + DBGridL0.DataSource.DataSet.Fields[5].AsInteger;
OutA:=OutA + DBGridL0.DataSource.DataSet.Fields[6].AsInteger;
OutC:=OutC + DBGridL0.DataSource.DataSet.Fields[7].AsInteger;
Application.ProcessMessages;
DBGridL0.DataSource.DataSet.Next;
end;
//выставляем статус новой часовой записи. нолные данные или нет
if m=3600 then status:=1 else status:=0; //если запись состоит из 3600 секунд данных
if m<>0 then //добавляем запись в приемник, если данные вообще есть
begin
FDQueryL[0].ExecSQL(
'INSERT INTO xxx (ID, TimeFrom, TimeTo, ID_CL, InA, InС, OutA, OutC, Status) VALUES ('+
c + IntToStr(idR) + c + ', ' + //ID
c + FormatDateTime('yyyy-mm-dd h:mm:ss', d) + c + ', ' + //TimeFrom
c + FormatDateTime('yyyy-mm-dd h:mm:ss', d+EncodeTime(1,0,0,0)) + c + ', ' + //TimeTo
c + IntToStr(line) + c + ', ' + //ID_CountingLine
c + IntToStr(InA) + c + ', ' +
c + IntToStr(InC) + c + ', ' +
c + IntToStr(OutA) + c + ', ' +
c + IntToStr(OutC) + c + ', ' +
c + IntToStr(status) + c + '); ');
idR:=idR+1;
end;
end;
d:=RecodeMilliSecond(d, 0); // это чтобы не накапливалась ошибка инкремента дат
d:=IncSecond(d,3600);
Application.ProcessMessages;
end;
FDQueryL[0].EnableControls; DBGridL0.DataSource.DataSet.EnableControls;
DBGridL0.Visible:=true;
Вот так костылём кое-как делаю, как видно я тут и прям по DBGrid лопачу и FDQuery, что на самом деле с одной базой связано, одним дата сетом. данные за 1 год обрабатываются СУТКИ!
Я правильно понимаю, что делаю это в режиме LiveDataWindowMode ? Я даже не использую FDTable вообще.
Толковой статьи как правильно организовать обработку не нашёл. только какие-то отдельные статьи.
пока что в них увидел такие советы, как кэширование:
FDQuery1.CachedUpdates := True;
...
FDQuery1.Edit;
...
FDQuery1.Post;
...
FDQuery1.Append;
...
FDQuery1.Post;
...
FDQuery1.ApplyUpdates;
FDQuery1.CommitUpdates;
FDQuery1.CachedUpdates := False;
Но тут мне не понятно сколько таких команд Append может быть максимум? как часто делать ApplyUpdates...
Видел советы использовать TFDMemTable. Но я т.к. новичок не понимаю даже как в общем это организовать?
сделать два TFDMemTable (источника и приемника) ? какими методами внутри пользоваться, edit/append/delete или sql запросами, что быстрее?
применять ли мне кэширование и tfdmemTable одновременно ?
Вопрос: как правильно и БЫСТРО обработать большой объем данных?
П.С. может дадите хорошую ссылку на статью, где описан принцип построения приложения, или классный исходник, где можно было бы подсмотреть как делают профессионалы (желательно с минимумом обращения к визуальным компонентам вообще, т.к. моё приложение я буду переделывать в консольное, для фоновой обработки). В будущем мне кстати понадобятся ещё потоки для одновременной обработки нескольких таких таблиц, есть ли готовые компоненты в firedac или пользоваться tthread, масса вопросов....