Autor Téma: IBQuery  (Přečteno 13084 krát)

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 577
  • Karma: 25
Re:IBQuery
« Odpověď #15 kdy: 06-10-2012, 10:46:16 »
1) Jasný praktický význam má počet záznamů pro uživatele, konkrétně pro zobrazení progressbaru. Přinejmenším pro moje uživatele je, soudě podle toho, s čím se na mě obrací, důležitější vidět, že operace probíhá a jak je daleko, než jak rychle se dohrabe k výsledku. (Jinými slovy, nevadí čekat, ale musí jít odhadnout, jak dlouho ještě budou čekat.)

2) Zjištění počtu záznamů předem je u některých typů dotazů hodně nákladné. Typicky u operací, kde složitý dotaz vytáhne z velké tabulky relativně málo záznamů a ty potom dalšími operacemi upravuji.

Jak teda zobrazuješ progressbar, když nevíš, kolik toho bude (RecordCount vždy nevrací hodnotu odpovídající skutečnému počtu) a "Zjištění počtu záznamů předem je u některých typů dotazů hodně nákladné"?

Jinak to zjištění počtu nebude nikdy náročnější, než ty data opravdu tahat. Projde se max. stejné množství dat, ale netahá se na klienta. On to ani nemusí být stejný dotaz - třeba můžeš přes select count zjistit počet záznamů v tabulce odpovídající podmínce, to prezentovat jako počet a dalším dotazem s joiny tahat ty skutečná data.

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 577
  • Karma: 25
Re:IBQuery
« Odpověď #16 kdy: 06-10-2012, 10:49:05 »
// FetchAll
To nepoznám. Pozriem sa na to.

Spomenul som si, že kedysi kdesi prečítal približne "DB nevie počet riadkov. Musíte použiť metódu Last." Takto to funguje. Platí to pre tabuľky aj dotazy.

Ona je to taky otázka efektivity - pokud taháš data částečně, tak ti DB může vrátit část dat a než je zpracuješ, tak bude k dispozici další část. V opačném případě budeš čekat, než se všechno vrátí, nic nedělat a pak to zpracovávat najednou. Je to asi jako kdyby ti maily nechodily každých pár desítek vteřin, ale přišlo ti to všechno najednou večer.

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 577
  • Karma: 25
Re:IBQuery
« Odpověď #17 kdy: 06-10-2012, 10:51:24 »
Hm, s TList-om akosi nepracujem. Čo nie je môže byť.
Len jedna otázočka, to pole je viac rozmerné s rôznymi typmi údajov. Zvláda to TList?. Alebo tam budem musieť použiť TObject?

TList interně používá pole, které zvětšuje podle potřeby,ale z pohledu uživatele té třídy tě to nemusí zajímat. Dávaly se tam snad objecty, takže si to můžeš přetypovat na co chceš, můžeš tam dávat třeba další TListy. Většina jazyků dneska podporuje generické typy (Delphi to má snad od nějaké verze umět taky), pak můžeš přímo říct, že to je třeba list stringů a bude ti vracet stringy bez nutnosti něco přetypovávat.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7424
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:IBQuery
« Odpověď #18 kdy: 06-10-2012, 10:58:35 »
// Jinak to zjištění počtu nebude nikdy náročnější, než ty data opravdu tahat. Projde se max. stejné množství dat, ale netahá se na klienta. On to ani nemusí být stejný dotaz - třeba můžeš přes select count zjistit počet záznamů v tabulce odpovídající podmínce, to prezentovat jako počet a dalším dotazem s joiny tahat ty skutečná data.

Tak tomu rozumiem. A je rozhodnuté. Aj keď tie údaje potrebujem natiahnuť, ale počet si zistím samostatným dotazom, aby som si mekomplikoval ten svoj. (Viď napr. GROUP  BY)

Ten TList si naštudujem.
Win11 64b, Delphi 12.2, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1574
  • Karma: 37
    • Pepak.net
Re:IBQuery
« Odpověď #19 kdy: 06-10-2012, 11:02:52 »
Jak teda zobrazuješ progressbar, když nevíš, kolik toho bude (RecordCount vždy nevrací hodnotu odpovídající skutečnému počtu) a "Zjištění počtu záznamů předem je u některých typů dotazů hodně nákladné"?
No tak například právě v případě, že si Dataset vytáhne z databáze celý resultset najednou, už se RecordCount použít dá.

Citace
Jinak to zjištění počtu nebude nikdy náročnější, než ty data opravdu tahat.
To jistě ne, ale pokud je N dostatečně velké, tak 2*N je o hodně větší než N+1...

Citace
Projde se max. stejné množství dat, ale netahá se na klienta.
V ideálním případě ano. Podle selského rozumu ano. V praxi někdy ne. Typicky, pokud původní dotaz obsahuje agregace.

Citace
On to ani nemusí být stejný dotaz - třeba můžeš přes select count zjistit počet záznamů v tabulce odpovídající podmínce, to prezentovat jako počet a dalším dotazem s joiny tahat ty skutečná data.
Jistě. V extrémních případech mi přijde lepší použít jednoduchý dotaz, který počet záznamů nadhodnotí, a pak holt ProgressBar skončí na na 100 procentech, ale na 80ti.

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 577
  • Karma: 25
Re:IBQuery
« Odpověď #20 kdy: 06-10-2012, 12:00:13 »
No tak například právě v případě, že si Dataset vytáhne z databáze celý resultset najednou, už se RecordCount použít dá.

Což něco stojí - pokud to taháš postupně, tak můžeš zpracovávat data dřív, než všechno dorazí. Pokud taháš všechno, tak třeba půl minuty zbytečně čekáš a pak to zpracování bude trvat o půl minuty déle.

Citace
Projde se max. stejné množství dat, ale netahá se na klienta.
V ideálním případě ano. Podle selského rozumu ano. V praxi někdy ne. Typicky, pokud původní dotaz obsahuje agregace.

Ono se to taky dost často chová tak, že první provedení dotazu trvá třeba i několikrát déle, než opakované, kdy se už řada dat nacachovala. Takže v některých případech může být ten count() pomalejší, než to vytažení dat. Pokud bys ho ale neudělal, tak to ty data bude tahat o to déle. Pomalý není ani tak ten count, jako to, že k datům přistupuješ poprvé.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3516
  • Karma: 112
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:IBQuery
« Odpověď #21 kdy: 07-10-2012, 18:45:37 »
Citace
Písal som, že počet záznamov potrebujem na nastavenie dĺžky poľa.
V tom bude patrně algoritmická chyba - předem neznámý počet záznamů se obvykle v poli neuchovává. Máš nějaký zásadní důvod, proč je neukládáš třeba do TListu, když už chceš zachovat přístup jako k poli?

Já to dělám třeba docela často - myslím tím dynamická pole.  Zvláště v případě kdy položka pole je record - věta načtená z DB. Nemusím myslet na uvolnovani paměti a přes record helpery s tim pěkně pracuji. Navíc je jaksi samozřejmě bez námahy typově korektní, což do příchodu generik byl docela opruz vždy definovat následníka TList. Samozřejmě to používám primárně v případech kdy nemažu záznamy, v opačném případě je výhoda TList a spol nesporná.
Embarcadero MVP - Czech republic

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 7424
  • Karma: 44
    • Verze Delphi: W11 + D11.3.1
Re:IBQuery
« Odpověď #22 kdy: 08-10-2012, 08:44:27 »
Tak tie úvahy o RecordCount mi dávajú zabrať. Budem čumieť do kódu aby som to nepotreboval. Okrem iného aj zobrazujem počet záznamov. To ovšem nemusí byť.
Včera sa mi stala takáto vec (zabil som s tým pár hodín):
Spustím Query a následne ďalší kde

- v selecte je len count(*)
- ostáva pôvodná časť FROM a WHERE
- prípadný ORDER BY je vyhodený

a vrátim si počet záznamov. V jednom prípade prípade mi hlásilo chybu (asi -303) konverzie stringu na "False"?

Ak som SQL spustil v TIBQuery, v ktorom sa predtým vykonal kompletný dotaz, tak to bolo OK. Vo všetkých ostatných prípadoch to padlo na chybu. Iný, aj doposiaľ nepoužitý, TQuery. Chyba zmizla ak som

Query.SQL.Text := ''; // pridal tento riadok
Query.SQL.Text := SQLText;

Vie to niekto (stretol sa s tým) vysvetliť?

Ak prejdem DataSet

WHILE not query.EOF do
begin
....
query.Next;

Tak by som, podľa mňa, nemal mať žiaden problém s Query.RecordCount - prosím o vyjadrenie.

Poznámka:
Ja tie DataSet-y komplet prechádzam a načítavam z nich všetky údaje napr. do
- LookUpComboBox
- VirtualTreeView
- do poľa pre ďalšie použitie, aby som nepracoval s DataSet-om. Možno to je nesprávny prístup (?). Napr. tie parametre programu, podľa ktorých sa určuje jeho správanie.

DBGrid nepoužívam.
Win11 64b, Delphi 12.2, FireBird 4.01
Expert na kladenie nejasne formulovaných otázok.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3527
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:IBQuery
« Odpověď #23 kdy: 08-10-2012, 08:59:41 »
Takže jednoznačne odporúčate použiť FetchAll a/alebo count(*)
Mam pocit, ze to stale nechapes: kdyz pouzijes count(*), tak uz nemusis delat zadne FetchAll ani Last a nepouzivas vubec RecordCount, ale pocet si prectes z result setu po tom selectu s count(*). To FetchAll je alternativa k tomu Last.


...
Musíte použiť metódu Last." Takto to funguje. Platí to pre tabuľky aj dotazy.a nespoliehať sa na
RecordCount + Last.
FetchAll a Last jsou alternativy, jak nastavit do RecordCount platny pocet zaznamu, ostatne treba konkretne u IBQuery je to implementovano tak, ze si zapamatuje v bookmarku soucasnou pozici, udela Last a pak pozici obnovi.

Ale uz jsem potkal query, ktere nedovoli se vracet, takze jak jednou udelas Last, tak sice ziskas RecordCount, ale uz se k jinym datum v result setu nedostanes, protoze jsou jednosmerne. Ale nepamatuji, ktere to konkretne byly.

Osobne se ridim tim, ze jakmile pouzivam Query, tak vzdycky ctu pocet pres count(*) a vzdycky prochazim result set od zacatku do konce pomoci while not Q.Eof do ...