[ jablan @ 19.02.2009. 21:47 ] @
Dakle, imam tabele:

Code:
dokumenti(id, datum, tip_dokumenta)
stavke(id_dokumenta, tip_stavke)


Stavki ima otprilike 10 po dokumentu.

I upit ovog tipa:

Code:
SELECT tip_dokumenta, tip_stavke, COUNT(*)
FROM dokumenti d
INNER JOIN stavke s ON d.id = s.id_dokumenta
GROUP BY tip_dokumenta, tip_stavke


Pitanje je kako indeksirati tabele.

Isto pitanje ako se u upit doda i WHERE uslov po datumu.
[ chachka @ 20.02.2009. 06:19 ] @
U izvršavanju ovog upita ne pomaže nikakav indeks, dok u izvršavanju varijante sa WHERE klauzulom pomaže indeks nad kolonom "datum" tabele "dokumenti" i nad kolonom "id_dokumenta" tabele "stavke".
[ jablan @ 20.02.2009. 07:39 ] @
Hvala, bojao sam se da je tako. Moraće da padne denormalizacija.
[ chachka @ 20.02.2009. 08:15 ] @
Denormalizacija? hm...

Ako tabela "dokumenti" ima N redova, uz 10 stavki po dokumentu dođe da tabela "stavke" ima 10*N redova, što je ukupno 11*N redova koje sve treba isčitati.

Ako bi se uradila denormalizacija tada bi ostala samo jedna tabela sa 10*N redova koje opet sve treba isčitati.

Koliki je dobitak na performansama?

(11-10)/11 = 9%!

Pitanje je da li će neki korisnik primetiti razliku od 9% u izvršavanju upita.

[ jablan @ 20.02.2009. 09:21 ] @
Ček, zar u slučaju denormalizacije (kopiranja kolona iz dokumenta u stavke) neću moći da napravim indeks (tip_dokumenta, tip_stavke) koji bi znatno ubrzao upit?
[ chachka @ 20.02.2009. 11:19 ] @
Ako nebudeš imao WHERE klauzulu u upitu, opet ti nikakav indeks nebi pomogao. Jednostavno je za prebrojavanje svega potrebno proći kroz sve redove, a to se najbrže radi bez indeksa. Indeks bi ti mogao pomoći da imaš MIN ili MAX umesto COUNT.
[ Zidar @ 20.02.2009. 18:25 ] @
@Jablan: Ako bi i denormalizovao, pa recimo imas tabelu sa 10 kolona, po jednu za svaku stavku. Ako bas SVAKI dokument ima 10 stavki, onda nema sta da se broji, broj stavkije uvek isti = 10. Naravno, broj stavki nije isti za svaki domumnet, neki ima 5 neki 7, neki 3, neki 10. To znaci da bi neke kolone u denormalizovanoj tabeli imale vrednost NULL. Tvoja tabela i kveri bi izgledao nekako ovako:

CREATE TABLE DenormalizovanaTabela (DocumentID int, Kolona 1 int, Kolona2 int, Kolona3 int... Kolna10 int)

SELECT
DocumentID
, BrojStavki = COALSCE(Stavka1,0) + COALSCE(Stavka2,0)+COALSCE(Stavka3,0)+...+COALSCE(Stavka10,0)
FROM DenormalizovanaTabela

Tesko da bi ovo bilo efikasnije od onoga sto imas, indeksirano ili ne. I nisam uveo tipove dokumenta u igru, onda bi se izraz za BrojStavki dodtno zakomplikovao, imali bi po jedan za svaki 'TipStavke'

U tvom slucaju denormalizacija bi bila vrlo neprakticna.

:-)
[ jablan @ 20.02.2009. 18:46 ] @
Nisam mislio na tu denormalizaciju (izvinjavam se ako sam se frljnuo pojmom, ali ipak mislim da nisam), već da jednostavno u tabelu stavke dodam polja datum i tip_dokumenta.
[ Zidar @ 20.02.2009. 21:24 ] @
Citat:
Nisam mislio na tu denormalizaciju (izvinjavam se ako sam se frljnuo pojmom, ali ipak mislim da nisam),
I sam nisam verovao da si na ovo mislio, ali je tako izgldealo, a pricu sam dao da neko ne bi stvarno pomislio da tako mozda treba

Kveri od koga si poceo je najnormalnija stvar i ako ti je to sporo onda imas neki drugi problem koji ne vidiimo na prvi pogled. Ako saljes mozda 50,000 dokumenata sa po 10 stavki u proseku u Access report, pa se report spor otvara, to je do Accesa, nije do kverija ....

[ jablan @ 21.02.2009. 10:09 ] @
Dakle, uz pretpostavku da je upit ok, zaključak je da nikakav indeks ne pomaže, čak ni id_dokumenta u tabeli stavke (naravno, njega ne planiram da brišem)?

Inače, radim sa nekih 500-tinak hiljada slogova u tabeli dokumenti (dakle, oko 5M stavki), i ne radi se o dokumentima i stavkama, preimenovao sam stvarne nazive zbog lakšeg objašnjavanja. Postgresql.
[ chachka @ 21.02.2009. 14:28 ] @
Indeksi ti nece pomoci - ali probaj denormalizaciju. Moja racunica verovatno nije tacna jer ne ukljucuje samu cenu joinovanja, koja na celim velikim tabelama može i sama biti veoma skupa.
[ .:Marvin:. @ 24.02.2009. 15:43 ] @
E, dobro, ne pomaze indeks.
Ali, da li si razmisljao o tome da ubacis neku kolonu koja se izracunava, u tabelu gde ti je zaglavlje, i tu da pise broj stavki?
U tom slucaju bi dosta izgubio kod inserta i update-a, ali znacajno dobio kod Selecta. Naravno, sve ovo pod uslovom da ti je jako bitna brzina selecta?
[ jablan @ 24.02.2009. 15:52 ] @
Citat:
.:Marvin:.: Ali, da li si razmisljao o tome da ubacis neku kolonu koja se izracunava, u tabelu gde ti je zaglavlje, i tu da pise broj stavki?

Ne može tako, jer se count računa i po tipu stavke, tj. jedan dokument ima različit broj stavki različitog tipa.

Inače, sad radim sa denormalizovanom tabelom (sve u jednoj tabeli) i čini mi se da je dosta brže i da će biti dovoljno. Nažalost, nisam merio brzine da bih mogao da stavim konkretne cifre.
[ zmau @ 27.02.2009. 15:59 ] @
Greota je zbog jednog upita praviti denormalizaciju. (Mislim, u principu, možda u tvom slučaju i nije.)
Ako imaš konačan (i dovoljno mali) broj tipova stavki, opet možeš da uradiš to što Marvin predlaže, samo što ćeš dodati više kolona.
Takođe, uvek možeš da imaš noćni job koji će da broji i pamti u pomoćnoj tabeli to što ti treba. A ako ti treba skroz ažuran podatak, lako ćeš dodati rezultate od današnjeg dana (sa indeksom po datamu, naravno). Sve ovo jeste nekakav workaround, ali mi se čini da je opet pristojnij od menjanja strukture tabela. Naročito ako te dve tabele (planiraš da) koristiš i u mnogim drugim upitima.
[ jablan @ 27.02.2009. 18:42 ] @
Citat:
zmau: Greota je zbog jednog upita praviti denormalizaciju. (Mislim, u principu, možda u tvom slučaju i nije.)

Heh, nažalost, ja i tabelu pravim zbog dotičnog upita (doduše, ne jednog, ali mnoštva sličnih).
Citat:
Ako imaš konačan (i dovoljno mali) broj tipova stavki, opet možeš da uradiš to što Marvin predlaže, samo što ćeš dodati više kolona.

Ima ih par desetina hiljada.
Citat:
Takođe, uvek možeš da imaš noćni job koji će da broji i pamti u pomoćnoj tabeli to što ti treba. A ako ti treba skroz ažuran podatak, lako ćeš dodati rezultate od današnjeg dana (sa indeksom po datamu, naravno).

Svih 5 miliona stavki su od jednog dana, učitavam nove i upite izvršavam svakog sata. Ovde ne postoji pojam "noći"...

Hvala u svakom slučaju...