powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / помогите ускорить обработку. FDMemTable почему-то работает медленно
14 сообщений из 14, страница 1 из 1
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953725
deamount
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
не пинайте. я начинающий. с БД сталкиваюсь впервые. понадобилось сконвертировать данные в таблице более 300 000 строк.
таблица вида: id, dateFrom, dateTo, lD_CL, inA, inB, status ...
записи периодами 15 минут (но не все). т.е. например dateFrom = '01.01.2020 10:00:00' dateTo = '01.01.2020 10:15:00' и т.д
понадобилось сконвертировать в 1 часовые. НО с доп проверкой их полноты и т.д....
До sql запроса я не смог догадаться, как голову ни ломал...
плюс нужна доп обработка, поэтому слобал на дельфи:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
var mtL, mtR, mt: TFDMemTable;
d,d1,d2: tdatetime;
s,id: string;
c:char;  idR, m, line, status, InA, InC, OutA, OutC, h:int64;
begin
  c:=chr(39);
  mtL:=TFDMemTable.Create(nil);  mtR:=TFDMemTable.Create(nil);

  FDQueryL[0].Connection:=FDConnectL[0];
  FDQueryR[0].Connection:=FDConnectL[0];
  FDQueryL[0].FetchOptions.Unidirectional := False;
  FDQueryR[0].FetchOptions.Unidirectional := False;
  FDQueryL[0].Sql.Text := 'SELECT * FROM source_table;';
  FDQueryL[0].Open;
  FDQueryL[0].FetchAll;
  FDQueryR[0].Sql.Text := 'SELECT * FROM destination_table;';
  FDQueryR[0].Open;
  FDQueryR[0].FetchAll;

//  mtL.Data:=FDQueryL[0].Data;
//  mtR.Data:=FDQueryR[0].Data;
  mtL.CopyDataSet(FDQueryL[0], [coStructure, coRestart, coAppend] );
  mtR.CopyDataSet(FDQueryR[0], [coStructure, coRestart, coAppend] );
  mtL.Open;
  mtR.Open;

  mtL.DisableControls;
  mtR.DisableControls;

  with mtR do
  begin
    LogChanges := False;
    FetchOptions.RecsMax := 300000;  //Sample value
    ResourceOptions.SilentMode := True;
    UpdateOptions.LockMode := lmNone;
    UpdateOptions.LockPoint := lpDeferred;
    UpdateOptions.FetchGeneratorsPoint := gpImmediate;
  end;
  mtR.BeginBatch;
  
  idR:=0;
  d:=EncodeDate(2019,6,1)+EncodeTime(1,0,0,0);   d1:=d;
  while d<now do
  begin
    for line := 4 to 20 do
    begin
      //выбитаем все что в 1 часе
      mtL.Filtered := False;
      //не обращайте внимания на кривизну кода фильтра
      mtL.Filter := '(ID_CL='+inttostr(line)+') AND '+
                    '(TimeFrom >= '+c+DateTimeToStr(d)+c+
                    ') AND ('+
                    'TimeFrom < '+c+FormatDateTime('dd.mm.yyyy h:mm:ss', IncSecond(d, 3599))+c+')';
      mtL.Filtered := true;
      //считаем сумму минут
      m:=0; InA:=0; InC:=0; OutA:=0; OutC:=0;
      mtL.First;
      while (not mtL.Eof) do
      begin
        m:=m+SecondOfTheDay(mtL.Fields[2].AsDateTime)-SecondOfTheDay(mtL.Fields[1].AsDateTime);
        InA:=InA + mtL.Fields[4].AsInteger;     InC:=InC + mtL.Fields[5].AsInteger;
        OutA:=OutA + mtL.Fields[6].AsInteger;   OutC:=OutC + mtL.Fields[7].AsInteger;
        Application.ProcessMessages;
        mtL.Next;
      end;
      //выставляем статус пакету
      if m=3600 then status:=1 else status:=0;
      if m<>0 then //добавляем записб в приемник
      begin
        with mtR do
        begin
          Append;
          Fields[0].AsInteger := idR;
          Fields[1].AsDateTime := d;
          Fields[2].AsDateTime := d+EncodeTime(1,0,0,0);
          Fields[3].AsInteger := line;
          Fields[4].AsInteger := InA;         Fields[5].AsInteger := InC;
          Fields[6].AsInteger := OutA;        Fields[7].AsInteger := OutC;
          Post;
        end;
        idR:=idR+1;
      end;
    end;
    d:=RecodeMilliSecond(d, 0);
    d:=IncSecond(d,3600);
    Application.ProcessMessages;
  end;
  mtR.EndBatch;

  mtL.EnableControls;
  mtR.EnableControls;

  FDQueryR[0].Close;
  FDQueryR[0].CopyDataSet(mtR);
  FDQueryR[0].Open;

  mtL.Free;     mtR.Free;     



обрабатывает около СУТОК !!! что я делаю неправильно ?
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953728
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
deamountчто я делаю неправильно ?

На первый взгляд, даже не читая документацию на отдельные использованные методы -
практически всё. Даже если у тебя не хватило фантазии на запрос - всегда остётся
возможность использовать ХП с курсором внутри. Но придётся чётко сформулировать логику
"доп.обработки".
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953730
deamount
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
доп обработка: доп поле status в таблице выставлять в зависимости от того, за весь ли час есть данные, превышена ли их погрешность, были ли ошибки при получении данных от оборудования.
все это рассчитывается из данных inA inB inC ...
ну для начала напрмер, сделать status=1 когда данные за весь час или status=0 когда данные не за весь час.

мда... что такое ХП и курсор вообще хз :(
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953735
deamount
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
поделитесь, пожалуйста, примером или ссылками, как правильно реализовать обработку.
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953738
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
deamountну для начала напрмер, сделать status=1 когда данные за весь час или status=0 когда данные
не за весь час.

Что такое "данные за весь час", в коде? Когда ты это определишь - сможешь внести это
условие в SQL оператор CASE.

deamountчто такое ХП и курсор вообще хз

ХП это "хранимая процедура". Как и курсор - ищется в документации по твоей СУБД, которую
ты не удосужился назвать.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953744
deamount
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
спасибо за ответы

записи периодами 15 минут (но не все). т.е. например dateFrom = '01.01.2020 10:00:00' dateTo = '01.01.2020 10:15:00' и т.д
понадобилось сконвертировать в 1 часовые
например строки
id=1, dateFrom = '01.01.2020 10:00:00' dateTo = '01.01.2020 10:15:00', 1, 2, 3
id=5, dateFrom = '01.01.2020 10:15:00' dateTo = '01.01.2020 10:30:00', 1, 2, 3
id=7, dateFrom = '01.01.2020 10:30:00' dateTo = '01.01.2020 10:45:00', 1, 2, 3
id=2, dateFrom = '01.01.2020 10:45:00' dateTo = '01.01.2020 11:00:00', 1, 2, 3
собираются в одну строку:
id=8, dateFrom = '01.01.2020 10:00:00' dateTo = '01.01.2020 11:00:00', 4, 8, 12, status=1

или
id=12, dateFrom = '01.01.2020 10:00:00' dateTo = '01.01.2020 10:05:00', 1, 2, 3
id=53, dateFrom = '01.01.2020 10:05:00' dateTo = '01.01.2020 10:10:00', 1, 2, 3
id=64, dateFrom = '01.01.2020 10:10:00' dateTo = '01.01.2020 10:15:00', 1, 2, 3
id=42, dateFrom = '01.01.2020 10:15:00' dateTo = '01.01.2020 10:20:00', 1, 2, 3
id=23, dateFrom = '01.01.2020 10:50:00' dateTo = '01.01.2020 11:00:00', 1, 2, 3
собираются в одну строку:
id=86, dateFrom = '01.01.2020 10:00:00' dateTo = '01.01.2020 11:00:00', 5, 10, 15, status=0 (0, т.к. нет данных с 10:20 до 10:50 )

извиняюсь, не обозначил базу - это MySQL
базу проектировал не я, софт производителя работает быстро.
значит там уже должны быть нужные ХП? я так понял ХП хранится в базе. поищу ..
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953745
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
deamountсобираются в одну строку:

И в чём проблема? Это тривиальный GROUP BY + SUM() + CASE WHEN COUNT(*) = 4 then 1 else 0
END as status.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953761
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov

Это тривиальный GROUP BY + SUM() + CASE WHEN COUNT(*) = 4 then 1 else 0

Нихрена не тривиальный COUNT(), у него надо чтобы произвольные отрезки времени покрывали весь час, тогда status = 1, а если какой-то интервал пропущен, то status = 0.
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953762
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alekcvpу него надо чтобы произвольные отрезки времени покрывали весь час

Значит их надо предварительно сгруппировать в 15-ти минутные. Я не в курсе поддерживает ли
MySQL derived tables, но ХП и тут справится.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953767
deamount
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
спасибо! дело сдвинулось с мертвой точки
пока что без учета статусов и доп обработки собрал суммы:
Код: sql
1.
2.
3.
4.
5.
6.
CREATE TABLE dest_table 
SELECT ID, TimeFrom, date_add(TimeFrom, INTERVAL 1 HOUR) AS TimeTo, ID_CL, sum(InA) AS InA, SUM(InB) AS InB, SUM(InC) AS InC, 1 AS Status

FROM source_table

GROUP BY ID_CL, DATE_FORMAT(TimeFrom,'%y-%m-%d %H:00:00')



мои ранние попытки были неудачными, потому что не знал функций обработки времени
Код: plsql
1.
DATE_FORMAT(TimeFrom,'%y-%m-%d %H:00:00')



ЗА 9 СЕКУНД вместо целых суток!
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953774
deamount
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov,

можно ли без функции добавить конструкцию
Код: sql
1.
IF SUM(UNIX_TIMESTAMP(TimeTo) - UNIX_TIMESTAMP(TimeFrom))=3600 THEN 1 ELSE 0


в мою выборку?

вот так ругается на синтаксис
Код: sql
1.
2.
3.
4.
5.
6.
7.
CREATE TABLE dest_table 
SELECT ID, TimeFrom, date_add(TimeFrom, INTERVAL 1 HOUR) AS TimeTo, ID_CL, sum(InA) AS InA, SUM(InB) AS InB, SUM(InC) AS InC, 
(IF SUM(UNIX_TIMESTAMP(TimeTo) - UNIX_TIMESTAMP(TimeFrom))=3600 THEN 1 ELSE 0) AS Status

FROM source_table

GROUP BY ID_CL, DATE_FORMAT(TimeFrom,'%y-%m-%d %H:00:00')


подскажите, как без хп верно написать запрос?
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953801
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
deamount,

Код: sql
1.
SELECT ... CASE WHEN Условие THEN 1 ELSE 0 END as status ...
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953814
Softologic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
deamount
ЗА 9 СЕКУНД вместо целых суток!

Начало пути... Оно такое, да
Тоже натыкался на похожие моменты, не так разительно, но все же... Оптимизация - весчь! Респект тем старшим товарищам по форуму :)
...
Рейтинг: 0 / 0
помогите ускорить обработку. FDMemTable почему-то работает медленно
    #39953842
deamount
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
alekcvp, спасибо, работает!
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / помогите ускорить обработку. FDMemTable почему-то работает медленно
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]