[ chemical brother @ 29.10.2012. 09:23 ] @
Pozdrav svima,

imam pitanje vezano za GROUP BY klauzulu.

Koliko je GROUP BY udar na performanse, postoje li neka pravila prilikom njegovog koriscenja, kako se GROUP BY rjesava unutar SQL Servera... ?

Ovo mi je bitno jer cu imati potrebu da na dosta mjesta koristim GROUP BY klauzulu.

Hvala
[ Dusan Kondic @ 30.10.2012. 11:21 ] @
Primer:
Code:

DECLARE @T TABLE (ArtiklId INT, ArtiklSifra VARCHAR(10), ArtiklNaziv NVARCHAR(50), 
DatumProdaje DATETIME, Kolicina INT, NabavnaCena DECIMAL(18,2), ProdajnaCena DECIMAL(18,2))

INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (1, '1001', N'RAM Memory 1Mb', '2012-10-01', 2, 1000.00, 1100.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (2, '1002', N'Motherboard', '2012-10-01', 1, 4000.00, 4500.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (3, '1003', N'Hard disc', '2012-10-01', 3, 6000.00, 6800.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (1, '1001', N'RAM Memory 1Mb', '2012-10-01', 3, 1000.00, 1100.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (2, '1002', N'Motherboard', '2012-10-01', 4, 4000.00, 4500.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (3, '1003', N'Hard disc', '2012-10-01', 1, 6000.00, 6800.00)

INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (1, '1001', N'RAM Memory 1Mb', '2012-10-02', 3, 1100.00, 1200.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (2, '1002', N'Motherboard', '2012-10-02', 2, 4200.00, 4600.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (3, '1003', N'Hard disc', '2012-10-02', 4, 6100.00, 6900.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (1, '1001', N'RAM Memory 1Mb', '2012-10-02', 1, 1000.00, 1100.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (2, '1002', N'Motherboard', '2012-10-02', 1, 4200.00, 4600.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (3, '1003', N'Hard disc', '2012-10-02', 5, 6100.00, 6900.00)

INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (1, '1001', N'RAM Memory 1Mb', '2012-10-03', 1, 1200.00, 1400.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (2, '1002', N'Motherboard', '2012-10-03', 3, 4300.00, 4800.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (3, '1003', N'Hard disc', '2012-10-03', 2, 6200.00, 6900.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (1, '1001', N'RAM Memory 1Mb', '2012-10-03', 1, 1200.00, 1400.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (2, '1002', N'Motherboard', '2012-10-03', 5, 4300.00, 4800.00)
INSERT INTO @T (ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, Kolicina, NabavnaCena, ProdajnaCena) 
VALUES (3, '1003', N'Hard disc', '2012-10-03', 6, 6200.00, 6900.00)

SELECT ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje, SUM(Kolicina) AS UkupnaKolicinaNaDan, 
AVG(NabavnaCena) AS SrednjaNabavnaCenaNaDan, MAX(ProdajnaCena) MaksimalnaProdajnaCenaNaDan, 
MIN(ProdajnaCena) MinimalnaProdajnaCenaNaDan FROM @T
GROUP BY ArtiklId, ArtiklSifra, ArtiklNaziv, DatumProdaje


Da bi olakšao SQL Server, razmisli da li možeš da selektuješ jednom sve podatke koji su ti potrebni i da ih smestiš u diskonektovanu tabelu (DataTable), ili neku listu (List<T>, ObservableCollection<T>) pa da podatke uzimaš iz te tabele po potrebi umesto da se stalno obraćaš serveru.
Druga stvar koju možda možeš da uradiš je da u diskonektovanoj tabeli držiš podatke koji ti se stalno ponavljaju
Code:

SELECT ArtiklId, ArtiklSifra, ArtiklNaziv FROM @Artikli

a da ostale podatke po potrebi tražiš sa smanjenim brojem kolona
Code:

SELECT ArtiklId, DatumProdaje, SUM(Kolicina) AS UkupnaKolicinaNaDan, 
AVG(NabavnaCena) AS SrednjaNabavnaCenaNaDan, MAX(ProdajnaCena) MaksimalnaProdajnaCenaNaDan, 
MIN(ProdajnaCena) MinimalnaProdajnaCenaNaDan FROM @T
GROUP BY ArtiklId, DatumProdaje

U slučajevima kada je statičnih polja mnogo, a onih koji ulaze u neku agregatnu funkciju malo, ovakav pristup je opravdan.
Pozdrav
[ mmix @ 30.10.2012. 11:52 ] @
Ako imas index na poljima u group by klauzuli performacne hit je skoro beznacajan jer ce SQL optimizovati pristup kroz in-memory hash tabelu na osnovu kljuca indeksa a sam scan tabele ce ici kroz indeks.

Sem toga univerzalni odgovor ne postoji jer performanse svakog upita zavise od toga sta agregiras i da li je agregacija single-table ili spanuje vise tabela. Moja preporuka je da se ne smaras mnogo sa time sta jeste sta nije superoptimalno i da trosis gomilu vremena na permature optimization, osiguraj da si tu grupacije pokrivene indeksima i pisi upite tako da resavaju biznis probleme na tacan i najelegatniji moguci nacin a ostalo prepusti query optimizatoru u samom SQLu. Bavi se dubljom optimizacijom samo tamo gde primetis neprihvatljivo niske performance.