Autor Téma: Rychlost QueryFilterRecord ve FireDAC  (Přečteno 302 krát)

Offline xnukes

  • Mladík
  • **
  • Příspěvků: 65
  • Karma: 1
    • Verze Delphi: XE7
    • Bludspeed s.r.o.
Rychlost QueryFilterRecord ve FireDAC
« kdy: 03-11-2017, 14:08:36 »
Ahojte,

mám takový problém a nevím jak ho vyřešit :D Mám SQL dotaz (MySQL) ktery JOINUJE 2 tabulky, kde je zhruba 3000 v te hlavni tabulce. Data z ni filtruju pomoci OnFilterRecord, bohužel toto není asi správná volba protože firedac selectne vše z dotazu a teprve pak vyhazuje zaznamy ktery neprojdou podminkou. A když nad tím tak přemýšlím tak nevím co tomu tak dlouho trvá, testuje se 11 filtrů pokud jsou zadané. Nemáte nějáký nápad jak to urychlit ? :) Díky

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 1780
  • Karma: 72
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #1 kdy: 03-11-2017, 14:26:08 »
Ok
Rated 1 time
Vygenerovat dotaz vcetne tech filtrů, at si to vyresi MySQL?
Embarcadero MVP - Czech republic

Offline xnukes

  • Mladík
  • **
  • Příspěvků: 65
  • Karma: 1
    • Verze Delphi: XE7
    • Bludspeed s.r.o.
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #2 kdy: 03-11-2017, 14:35:18 »
Vygenerovat dotaz vcetne tech filtrů, at si to vyresi MySQL?
Tomuhle jsem se chtěl vyhnout, jelikož mám tak cca 20 formů používající tento objekt který filtruje pomoci onFilterRecord, a předělat by to znamenalo předelat 20 formů :) Ale asi mi nic jinyho nezbyde.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 2996
  • Karma: 29
    • Verze Delphi: XE7 professional
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #3 kdy: 03-11-2017, 14:54:38 »
Urob si jednu triedu, ktorá Ti bude vracať text SQL podľa typu formulára. A žiadne formuláre nemeníš.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 431
  • Karma: 21
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #4 kdy: 03-11-2017, 15:33:26 »
Predtim nez se pustis do optimalizaci, zkus pohledat nejaky code profiler. Ten ti rekne jaka cast kodu je "pomala".

U kodu ktery jsi mi poslal je par veci k optimalizaci. Nebudu ho bez svoleni publikovat, takze jen slovy; ulozil bych si fixni kolekci sloupcu (namisto opakovaneho dotazovani FieldByName). Stejne tak hodnoty filtrovacich komponent. Oboji stoji nejake drobne. A konecne, jakym zpusobem chces filtrovat (chces zaznam ponechat pokud se "rovnaji" vsechny filtrovaci komponenty, nebo alespon jedna z nich)?

Momentalni implementaci mas napsanou v pseudokodu takto:

Kód: Delphi [Vybrat]
  1. procedure TMyForm.FDQueryFilterRecords(DataSet: TDataSet; var Accept: Boolean);
  2. begin
  3.   // nikdy nenastavis Accept na True, a nasleduje serie podobnych podminek
  4.  
  5.   // pokud se pseudohodnota ziskana z Field1.Value rovna Filter1.Value, nastavis Accept do stavu False...
  6.   if Field1.Value = Filter1.Value then
  7.     Accept := False;
  8.   // ...nicmene neni treba pokracovat, protoze tady uz mas jasno, ze se radek do datasetu nedostane; proto neni treba pokracovat
  9.   if Field2.Value = Filter2.Value then
  10.     Accept := False;
  11. end;
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 1780
  • Karma: 72
    • Verze Delphi: D5,D2007, DXE, DXE2 + 2 poslední (Tokyo)
    • O Delphi v češtině
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #5 kdy: 03-11-2017, 16:03:24 »
Great
Rated 1 time
Jen bych podotknul, ze opakovane pouziti FieldByName nestoji drobne, ale celkem vyznamne zpomaleni a da se tim hodne usetrit. I kdyz vyssi verze Delphi pouzivaji pro FieldByName hash, porad je to casova penalizace a tim co rika Delphin to minimalizujes.
Embarcadero MVP - Czech republic

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 431
  • Karma: 21
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #6 kdy: 03-11-2017, 18:40:23 »
Jen bych podotknul, ze opakovane pouziti FieldByName nestoji drobne, ale celkem vyznamne zpomaleni a da se tim hodne usetrit. I kdyz vyssi verze Delphi pouzivaji pro FieldByName hash, porad je to casova penalizace a tim co rika Delphin to minimalizujes.

Pravda. Mel jsem byt presnejsi, moje chyba (mam k dispozici kod o kterem se bavime) :-[ Ta FieldByName drobnost je opakovana pro 11 ruznych sloupcu v kazdem volani metody udalosti OnFilterRecords (coz uz je vic nez drobnost).

Ohledne interne pouziteho dictionary pro hledani fieldu podle nazvu, nerekl bych ze to byla ze strany EMBT nejlepsi volba. K tomu pozlatku v podobe dictionary je totiz treba pricist "payload" hashovani klice a z praktickeho hlediska (pri "smysluplnem" poctu sloupcu tabulky) by mohla byt rychlejsi prosta iterace pole a porovnani bufferu 2 stringu. Obecne, dictionary neni pro "par" polozek z pohledu vykonu vhodna kolekce.
« Poslední změna: 03-11-2017, 19:04:49 od Delfin »
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 1866
  • Karma: 91
    • Verze Delphi: D2007, XE3, DX10
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #7 kdy: 03-11-2017, 19:11:03 »
Great
Rated 1 time
Ohledne interne pouziteho dictionary pro hledani fieldu podle nazvu, nevim jestli to byla ze strany EMBT dobra volba.
Jeste pred tim, nez se Borland k necemu takovemu odhodlal, jsem si udelal potomka datasetu, ktery si pri prvnim pouziti FieldByName vytvoril binarni index, pokud byl pocet poli vetsi nez cosi, jinak delal iteraci. A delal jsem si docela podrobna mereni.

Urcite jsem o tom nekolikrat v minulosti psal, o kolik se pristup zrychlil: dere se mi do hlavy, ze 5x ale HOSIP a ani ty prispevky, ani ten kod nemuzu najit :'(

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 431
  • Karma: 21
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #8 kdy: 03-11-2017, 19:28:52 »
Jeste pred tim, nez se Borland k necemu takovemu odhodlal, jsem si udelal potomka datasetu, ktery si pri prvnim pouziti FieldByName vytvoril binarni index, pokud byl pocet poli vetsi nez cosi, jinak delal iteraci. A delal jsem si docela podrobna mereni.

Urcite jsem o tom nekolikrat v minulosti psal, o kolik se pristup zrychlil: dere se mi do hlavy, ze 5x ale HOSIP a ani ty prispevky, ani ten kod nemuzu najit :'(

To by bylo super videt v primo TDictionary (idealne externe nastavitelne). Jeste by se dala pro iteraci pridat moznost uceni se nejpouzivanejsich klicu, a ty s pocty pouziti topovat na "vrchol" pole (aby se nemuselo podle ulozene statistiky vyuziti klicu tak "hluboko" iterovat). Ale to uz je mikrooptimalizace (byt porad snadno implementovatelna) ::) :) Ostatne, podobnym zpusobem by se daly cachovat i hashe. Hm, asi si pro radost vyrobim dictionary ;D
« Poslední změna: 03-11-2017, 19:36:14 od Delfin »
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 1866
  • Karma: 91
    • Verze Delphi: D2007, XE3, DX10
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #9 kdy: 03-11-2017, 19:35:17 »
Great
Rated 1 time
ani ten kod nemuzu najit :'(
Kód: Delphi [Vybrat]
  1.   //------------+---------------------------------------------------------------
  2.     function    TSQLAbstractQuery.__GetNamedFields
  3.                 (const aName:ANSIString): TField;
  4.   //------------+---------------------------------------------------------------
  5.     var
  6.       Idx:    integer;
  7.       Fields: TFields;
  8.     begin
  9.       // Build field index to speed-up searching field by names
  10.       if not Assigned(FFieldIndex) then
  11.         begin
  12.           if FIndexFields then
  13.             begin
  14.               Fields                    := self.Fields;
  15.               FFieldIndex               := TStringListEx.Create;
  16.               FFieldIndex.Capacity      := Fields.Count;
  17.               for Idx:=0 to Fields.Count-1 do
  18.                 FFieldIndex.AddObject(Fields[Idx].FieldName,Fields[Idx]);
  19.               FFieldIndex.ASCIIMode     := TRUE;
  20.               FFieldIndex.Duplicates    := dupError;
  21.               FFieldIndex.Sorted        := TRUE;
  22.               if Assigned(AppEnv) and AppEnv.AppBool[apbxTraceSQL] then
  23.                 begin
  24.                   Trace('== Field names in result set:');
  25.                   for Idx:=0 to FFieldIndex.Count-1 do
  26.                     TraceFmt('   Fields[%d].FieldName=%s',[Idx,FFieldIndex[Idx]]);
  27.                 end;
  28.             end;
  29.         end;
  30.       // If field index is available use it
  31.       if Assigned(FFieldIndex) then
  32.         begin
  33.           Idx := FFieldIndex.IndexOf(AName);
  34.           if Idx>=0 then
  35.             begin
  36.               Result := FFieldIndex.Objects[Idx] as TField;
  37.               exit;
  38.             end;
  39.         end;
  40.       // Otherwise call native full scan for name
  41.       Result := _GetNamedFields(AName);
  42.     end;
  43.  
Ale ten prispevek, co to udelalo s rychlosti se mi nevede vyhledat a merit to znovu nebudu :-( Ale uz to bylo davno, kdo vi, jestli tenkrat uz fungoval tenhle server nebo jestli to bylo jeste na Zahradnikove list serveru, nevim)

Offline Delfin

  • Hrdina
  • ****
  • Příspěvků: 431
  • Karma: 21
  • SW konzultant
    • Verze Delphi: 2009, Tokyo
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #10 kdy: 03-11-2017, 21:09:13 »
Pro dane vyuziti je to super reseni (prosty binary search string listu). Byt vyvojarem EMBT, implementoval bych to stejne (pokud nekdo touzi mit stovky, ne-li tisice sloupcu v tabulce [kdy se dictionary muze vyplatit], at za to trpi). Me mezitim od toho napadu vlastniho dictionary odradil fakt ze on vlastne klic muze byt i komplexni datova struktura, ne jen string :'( Dneska uz Delphi radeji necham :)
A co chudinky ovce? Koupíš jim snad plovací vesty? Nebo jim nasadíš chůdy? Ještě lepší, kdybys je zkřížil s delfíny na ovce hopkavé!

Offline xnukes

  • Mladík
  • **
  • Příspěvků: 65
  • Karma: 1
    • Verze Delphi: XE7
    • Bludspeed s.r.o.
Re:Rychlost QueryFilterRecord ve FireDAC
« Odpověď #11 kdy: 06-11-2017, 10:54:32 »
Kluci dekuju všem za informace, vyřešil jsem to nakonec vygenerovaním SQL dotazu, čímž jsem se dostal na hodně solidní milisekundy :)

onFilterRecords jsem nakonec nechal jen v gridech kde je očekáváno málo záznamu, nicméně jsem tuto proceduru optimalizoval (Díky Delfínku).

 

S rychlou odpovědí můžete používat BB kódy a emotikony jako v běžném okně pro odpověď, ale daleko rychleji.

Jméno: E-mail:
Ověření:
Kolik je šest plus čtyři (slovem):