[ X Files @ 16.05.2007. 13:07 ] @
Pozdrav,

Imam par pitanja u vezi dizajna baze, brzine odziva (sql) i AutoNumber PK.

Pretpostavimo da u nekom posmatranom sistemu imam 'hijerarhijsku' strukturu,
pa PK za podredjenu tabelu pravim od celog PK nadređene tabele, sa dodatkom
nekog novog atributa koji dovodi do jedinstvenosti sloga u podređenom entitetu,
i tako nekoliko nivoa, mozda 8. (nije bas sve tako pravolinijski, ali generalno
jeste cista hijerarhija).

Neke od hijerarhijski najvisih tabela imaju 'savrsene' kandidate za PK, recimo:
naziv drzave, naziv pasmine (rase psa), itd.

Medjutim, naziv pasmine je relativno dugacak string, i on bi se kroz hijerarhiju
formiranja PK u podredjenim entitetima stalno provlacio. Da ne pominjem i druge
relativno dugacke stringove koji se kombinuju sa prethodnim, takodje dugackim.

Stoga, odlucio sam se da ipak PK svuda bude AutoNumber, a da ti 'savrseni' kandidati
za PK budu samo No Duplicates, i nista vise.

Velicina baze se znacajno smanjila, pretpostavljam zbog manjih indeksnih datoteka,
koje je lakse odrzavati zbog prirode zapisa brojeva nasuprot stringovima.

Ostala mi je jos samo jedna nedoumica, šta se dogadja sa brzinom odziva nakon nekog
SQL upita u ovako projektovanoj bazi (sa AutoNumberima umesto Stringovima)?

Nisam mogao sam da isprobam zbog neadekvatnog broja podataka, ali zdrav razum mi
govori da je opet lakse (brze) izvrsiti sortiranje brojeva nego stringova gde ima
vise procesorskog rada...

Sta biste vi uradili u ovom slucaju, tj. sta bi bilo ZA a sta PROTIV ovakve moje
odluke?

[ Miloš Baić @ 16.05.2007. 16:38 ] @
Kad se modeluje baza, neophodno je pre toga uočiti sve entitete, entitete poveznike i korektno izvršiti normalizaciju. Da ne teorišem previše, možeš kreirati tabele šifarnike koje će sadržati, npr., dva atributa(id(PK),naziv) i u tabele poveznike ćeš spram potrebe vršiti evidenciju tih šifri, gde može i nastati složeni primarni ključ.
Npr:
# - Primary Key
$ - Foreign Key
Kontinent(#id_kontitnet, naziv_kont)
Države(#id_države, #$id_kontinent, naziv_drž) - predpostvka da dve države mogu imati isti naziv na različitim kontinentima (možda i ne postoji!?!), a id_kontinent referencira ka svojoj baznoj tabeli "Kontinent".
Rasa(#id_rasa, naziv_rase)

Tabela poveznik između njih bi mogla izgledati ovako:
Psi(#$id_države, #$id_rasa)

Dakle, složeni ključ se sastoji iz dva atributa koja istovremeno referencijaju ka svojim baznim tabelama, tj. šifarnicima, možeš uočiti da nismo stavili atribut id_kontinent, jer on već referencira u tabeli "Države", iz prostog razloga da ne bi došlo do redudanse. Tu možeš napraviti upit (ugnježdeni ili prirodno spajanje) na osnovu kojeg ćeš dobiti određen set podataka sa nazivom rase, nazivom kontinenta i nazivom države.

Istina je da će se upit brže izvršiti ako se spajanje vrši po atributu koji je numeričkog tipa, sa manje karaktera, nego neki string koji ima npr. 20 karaktera.

BTW, ne znam da li je primer dobar da ti da odgovor na tvoje pitanje s obzirom da sam nabrzinu odgovorio, ali verujem da ako nije već će neko kompetentan reagovati.
[ X Files @ 16.05.2007. 17:10 ] @
Citat:

Istina je da će se upit brže izvršiti ako se spajanje vrši po atributu koji je numeričkog tipa,
sa manje karaktera, nego neki string koji ima npr. 20 karaktera.

Mene upravo ovo zanima. Jos kad bih pronasao negde da je ovo zapisano 'crno na belo', u nekoj knjizi pa da idem ;) ...

Relaciona shema bi bila nekako ovako:

[att_img]

(gde god se vidi, na nekoliko mesta: opis, naziv, vrsta, ... moglo b da se uzme za PK, ali ja sam ipak odabrah NUMERICKI ID)

Upit bi bio otprilike ovako:
Code:

SELECT x.grupa_id, x.sekcija_id, x.podsekcija_id, d.naziv, g.naziv_lok, x.vrsta, x.cacib, x.radni_zadatak_id
FROM GRUPA AS a, SEKCIJA AS b, PODSEKCIJA AS c, REGION AS d, POREKLO AS e, RADNI AS f, RASA AS g, PASMINA AS x
WHERE (d.naziv='Germany') // <--- OVDE STAGOD JOS KONKRETNO ZA PRETRAGU 
And (a.broj=b.grupa_id)
And (b.grupa_id=c.grupa_id)
And (b.broj=c.sekcija_id)
And (c.grupa_id=e.grupa_id)
And (c.sekcija_id=e.sekcija_id)
And (c.broj=e.podsekcija_id)
And (d.id=e.region_id)
And (e.grupa_id=x.grupa_id)
And (e.sekcija_id=x.sekcija_id)
And (e.podsekcija_id=x.podsekcija_id)
And (e.region_id=x.region_id)
And (f.id=x.radni_zadatak_id)
And (g.id=x.rasa_id);

[ negyxo @ 16.05.2007. 20:01 ] @
Ako radis na SQL Serveru prvo sto ces uociti na BOL kada budes citao o relacijama (kandidatima za PK, FK) je da stavis sto je moguce manje polje, jer sto je manje polje brze je izvrsavanje. Ovo mozes i sam testirati nad par tabela. Ja sam svojevemeno uporedjivao performance GUID i int kao IDENTITY i razlike su znacajne bile u korist obicnog int. Idealno bi bilo kada bi radio samo sa prirodnim 'kljucevima' ali problem koji nastaje sa njima je sto prirodni kljucevi niti su nekad kratki, niti su iz jednog 'polja', pa zato u praksi je teze raditi sa njima (valjda ce jednog dana RDBMS proizvodjaci skontati da relacije ne treba da se mapiraju na polja nego na entitete, a sam tip tih relacija interno sam RDBMS da vodi). Otiso ja malo u off topic :)
Nego kod tog dizajna koji si odlucio ja bi najpre utvrdio kog obima ce se koristiti taj program i koliko podataka ce se skladistiti, jer iako su nazivi dugacki, ako su podaci u tabelama reda par hiljada, mislim da se u vecini 'osrednjih' upita nece toliko osetiti to ubrzanje sa char na int, tj. veorvatno u benchmarku hoce ali u realnom radu, najveci bottleneck su komunikacija sa bazom i prosledjivanje podataka front endu. I za kraj jedino sto bi te savetovao je da ako vec stavis int autonumber za PK, onda dodelis indexe i nazivima.

PS. Kakav to program pravis? Zanimljivo da me je upravo jedan drug zamolio da mu namestim jedan program za kategorizaciju pasa, posto mu je potreban prilikom izlozbe pasa.
[ X Files @ 16.05.2007. 20:05 ] @
Citat:

I za kraj jedino sto bi te savetovao je da ako vec stavis int autonumber za PK, onda dodelis indexe i nazivima.

Hvala na objasnjenu. Indekse jesam dodelio i nazivima.
[ Zidar @ 17.05.2007. 16:25 ] @
Gledajuci dijagram, ne vidim da si nesto lose logicki uradio, deluje OK.

Jedan predlog imam, ako nije kasno. Budi kosistentan u imenovanju atributa. Na primer, u nekoliko tabela imas atribut 'Broj'. kTo je verovatno neki broj 'rekorda' (autonumber?). Sta tu ne valja?

U tabeli Grupa, imas polje 'Broj' i to ti je PK. U redu, ako samo ovu tabelu posmatras.
U tabeli sekcija, ima spolje 'Broj' koje nije ni u kakvoj vezi sa Grupa.Broj. Imas zatim vezu Sekcija.Grupa_ID = Grupa.Broj
Zar nije bilo lakse da u tabeli Grupa, odmah kazes 'Grupa_ID'? Ovako, Grupa_ID je Grupa_ID svuda osim u maticnoj tabeli.

Isto i za atribut koji zoves ID u maticnim tabelama - Region.ID = druge_tabele.Region_ID, Rasa.Id = druge_tabele.Rasa_ID

Toplo preporucujem da se atributi koji se migriraju u druge tabele zovu isto u SVIM tabelama.

I koristi JOIN operator umesto WHERE. WHERE sluzi da se postavi uslov, a ne da se povezu dve tabele (mada moze). Za povezivanje tabela sluzi JOIN. Razlog? Ako bas nista drugo, onda jasnoca pisanja i razumevanje 'koda'

Ako ne radis u Accessu, malo formatiranja ne bi skodilo, na primer ovako:
Code:

SELECT 
    x.grupa_id
   , x.sekcija_id
   , x.podsekcija_id
   , d.naziv
   , g.naziv_lok
   , x.vrsta
   , x.cacib
   , x.radni_zadatak_id
FROM GRUPA AS a
JOIN SEKCIJA AS b
       ON a.broj=b.grupa_id
JOIN PODSEKCIJA AS c
       ON b.grupa_id=c.grupa_id
        And b.broj=c.sekcija_id
JOIN REGION AS d
       ON d.id=e.region_id
JOIN POREKLO AS e
       ON (c.grupa_id=e.grupa_id)
       And (c.sekcija_id=e.sekcija_id)
       And (c.broj=e.podsekcija_id)
JOIN  PASMINA AS x
       ON (e.grupa_id=x.grupa_id)
        And (e.sekcija_id=x.sekcija_id)
        And (e.podsekcija_id=x.podsekcija_id)
        And (e.region_id=x.region_id)
JOIN  RADNI AS f
        ON f.id=x.radni_zadatak_id
JOIN RASA AS g
       And (g.id=x.rasa_id);
WHERE (d.naziv='Germany') // <--- OVDE STAGOD JOS KONKRETNO ZA PRETRAGU 








[ X Files @ 17.05.2007. 17:20 ] @
Citat:

Jedan predlog imam, ako nije kasno.

Ne, nije kasno. Model koji sam prikazao je tek jedna skica.

Citat:

Budi kosistentan u imenovanju atributa. Na primer, u nekoliko tabela imas atribut 'Broj'. kTo je verovatno neki broj 'rekorda'
(autonumber?). Sta tu ne valja? U tabeli Grupa, imas polje 'Broj' i to ti je PK. U redu, ako samo ovu tabelu posmatras.
U tabeli sekcija, ima spolje 'Broj' koje nije ni u kakvoj vezi sa Grupa.Broj. Imas zatim vezu Sekcija.Grupa_ID = Grupa.Broj
Zar nije bilo lakse da u tabeli Grupa, odmah kazes 'Grupa_ID'? Ovako, Grupa_ID je Grupa_ID svuda osim u maticnoj tabeli.
Isto i za atribut koji zoves ID u maticnim tabelama - Region.ID = druge_tabele.Region_ID, Rasa.Id = druge_tabele.Rasa_ID
Toplo preporucujem da se atributi koji se migriraju u druge tabele zovu isto u SVIM tabelama.

Ovo je dobar savet. Promenicu svakako. Slazem se da treba stvoriti naviku da se stekne stil imenovanja atributa.

Citat:

I koristi JOIN operator umesto WHERE. WHERE sluzi da se postavi uslov, a ne da se povezu dve tabele (mada moze). Za povezivanje
tabela sluzi JOIN. Razlog? Ako bas nista drugo, onda jasnoca pisanja i razumevanje 'koda'

Takodje dobar savet. Da budem iskren, kako i ne radim nista profesionalno sa bazama podataka nisam ni znao kako se
JOIN koristi, ovako imam neku sliku, pa cu istraziti u tom pravcu.

Citat:

Ako ne radis u Accessu, malo formatiranja ne bi skodilo, na primer ovako:

Primer sam upravo testirao u Accessu (bio mi je pri ruci), i on je formatizovao po svome, a ja sam samo odradio neki lagani
copy&paste uz malo dorade.

Hvala za upit! Koristice mi svakako.