Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / помогите ускорить обработку. FDMemTable почему-то работает медленно / 14 сообщений из 14, страница 1 из 1
02.05.2020, 15:33
    #39953725
deamount
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите ускорить обработку. FDMemTable почему-то работает медленно
не пинайте. я начинающий. с БД сталкиваюсь впервые. понадобилось сконвертировать данные в таблице более 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
02.05.2020, 15:43
    #39953728
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите ускорить обработку. FDMemTable почему-то работает медленно
deamountчто я делаю неправильно ?

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

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

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

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

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

записи периодами 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
02.05.2020, 17:13
    #39953745
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите ускорить обработку. FDMemTable почему-то работает медленно
deamountсобираются в одну строку:

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

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

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

Значит их надо предварительно сгруппировать в 15-ти минутные. Я не в курсе поддерживает ли
MySQL derived tables, но ХП и тут справится.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
02.05.2020, 19:12
    #39953767
deamount
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите ускорить обработку. FDMemTable почему-то работает медленно
спасибо! дело сдвинулось с мертвой точки
пока что без учета статусов и доп обработки собрал суммы:
Код: 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
02.05.2020, 20:07
    #39953774
deamount
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите ускорить обработку. FDMemTable почему-то работает медленно
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
02.05.2020, 22:44
    #39953801
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
помогите ускорить обработку. FDMemTable почему-то работает медленно
deamount,

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

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


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