

SQL dotaz
Zdravím, potřeboval bych optimalizovat SQL dotaz, ale nemám představu jak přesně...
Zadání: Potřebuji z tabulky níže vybrat řádky, které jsou nejnovější k hodnotě key_id, ale přitom daný řádek má status = 1
id key_id tstamp status
----------------------------------
9 1 1412067222 1
8 2 1412067174 2
7 4 1412067126 2
6 4 1412067078 1
5 2 1412067030 2
4 3 1412066982 1
3 2 1412066934 1
2 1 1412066886 2
1 3 1412066838 1
Výstup by pak měl vypadat takto:
id key_id tstamp status
----------------------------------
9 1 1412067222 1
4 3 1412066982 1
Současný dotaz vypadá takto:
SELECT * FROM tabulka as t
WHERE t.tstamp >= (SELECT max(tstamp) FROM tabulka WHERE key_id = t.key_id)
AND t.status=1
Jelikož mám v tabulce skoro 500 000 záznamů, tak tento dotaz trvá na mém serveru kolem 4 vteřin.
Děkuji za pomoc
Jinak jak už zaznělo, funkci Max bys měl použít nad co nejmenším počtem záznamů, tedy je vhodná maximální předfiltrace, protože předpokládám, že "status=1" bude mít mnoho záznamů.
Jinak ještě, pokud záznamy přibývají výlučně na základě časového sledu, tak by nebylo od věci předomezit výběr pomocí SELECT TOP/LAST nad seřazeným id, řekněme 1000 řádek (záleží na tom, jak často se daný jev vyskytuje - toto není univerzální optimalizace!!). Zde pak přijde samozřejmě vhod index nad polem id.
edit: a jinak to vidím tak, že všechny key_id sis měl normalizovat do separátní tabulky, najoinovat a selektovat z ní, nikoli odkazem na celou velkou tabuli.
No ano, na max(tstamp) se ptá dotaz (SELECT max(tstamp) FROM tabulka WHERE key_id = t.key_id) a to je průměrně 15 řádků.
Jde o to, že potřebuji vypsat všechny záznamy "key", které mají poslední záznam v tabulce tabulka status = 1
jenže na ten "průměr" 15 řádků musí databázový stroj projít celý půlmilion řádků (a to tolikrát, kolikrát tam máš různé hodnoty key_id). A vvvvo tom to je.
To je pravda, tak jak by tedy měl ten dotaz vypadat lépe? Jde to vůbec?
Takhle jsem to lamoidně naklikal v Accessu (psaní selectů není zrovna má silná stránka):
tabulka "normaliz" obsahuje jen jedno pole, key_id, které funguje jako primární klíč vztahu 1:N vůči tabulce "tabulka" (tahle tabulka se dá samozřejmě generovat dotazem, nebo rovnou udělat jako dotaz)
Pravděpodobně to půjde ještě dále optimalizovat, ale na to jsou tu jiní kabrňáci, rozhodně neaspiruju na titul krále SQL
Díky za snahu, ale bohužel ani toto není ono
Výpis z tabulky výše je tento:
ale měl by být takový:
v tom případě máš chybu v zadání:
edit: zajímalo by mě spíše, zda to bylo rychlejší?
Ano rychlejší to je, ale nevypíše to to, co potřebuji, možná jsem to napsal tak, že se to dá pochopit více způsoby
ne, napsal jsi to tak, že se to dá pochopil jen tím jedním způsobem
, tj. vybrat nejnovější řádky se status 1 pro všechny key_id 
cize ak nejake key_id sa nachadza na 2 a viac riadkoch, ale aspon jedno z nich ma status <> 1, tak uz vo vystupe dane key_id byt nesmie?
lebo to dost meni logiku toho, co si popisal na zaciatku.
to by tam nemohly ale být ani key_id 1 a 3..
Pokud je key_id = 2 a nejnovější status = 2, tak key_id = 2 vůbec nezobrazovat.
Zobrazit pouze key_id, který má nejnovější status = 1
chtěl jsi napsat, že pokud pro dané key_id existuje nejnovější status > 1, tak nevypisovat poslední key_id = 1..
V tom případě se obávám, že to musíš řešit opravdu iteračně, ale pak bych si nejprve udělal select TOP xxx
edit: leda bys do "having" přidal celý další subselect porovnávající max(stamp) pro status <> 1 menší než timestamp
Ano, tak jsem to myslel
Tak v tom případě bych možná navrhnul úpravu databáze přidáním tabulky Status1, kde by v podsatě stačil jen jeden sloupec (i když pořadí by tam mohlo být vždy), ve kterém by program při ukládání, respektive aktualizaci statusu z a/nebo na 1 přidával a nebo mazal indexy odpovídající ID v první tabulce. Status by se tedy vůbec nenacházel v první tabulce (paralelne k tomu by mohla být tabulka Status2, kde by zase byly indexy těch ostatních záznamů).
Pak jediné, co by ti stačilo projet indexy (ID) záznamů v tabulce Status1, jestli se jim neschodují key_ID a ty nejnovější vypsat.
tak, normalizace většinou řeší tyhle problémy s podivnými a zbytečně složitými selecty.
skus takto:
Bohužel, prázdný výsledek...
sry, nema tam byt group by status ale group by key_id
ale prazdne by to byt nemalo.
Paráda, funguje
pecka pecka
kleslo to na krásných 0,5vteřin
díky
Presne takýmto spôsobom by som to riešil. Len by som nevytváral view, ale by som to dal rovno do toho selectu: