07. november 2007 - 14:13Der er
8 kommentarer og 1 løsning
Avanceret søgning
Hej!
Jeg er ved at lave en avanceret bruger søgning, som jeg gerne vil lave så effektiv som muligt.
For at simplificere det kan vi sige, at man kan søge på: - køn (0 = hunkøn,1 = hankøn,2 = par) - alder (0->99) - bopæl (0 = jylland, 1 = fyn, 2 = sjælland)
Jeg ville altså lave tabellerne således (igen simplificeret):
tableUsers - idUser - strUsername
tableGenderToUsers - idGender - ridUser
tableAgeToUsers - idAge - ridUser
tableAreaToUsers - idArea - ridUser
Det er muligt at vælge f.eks. alle aldersgrupper, men kun søge efter folk i odense - hvilket gør det temmeligt ubrugeligt blot at lave en enkelt table med indexes. Derfor har jeg lavet index-tabellerne.
Mit spørgsmål er så - hvordan ville en effektiv SELECT sætning se ud, hvis man f.eks. ville hente: - Alle brugere fra FYN med en alder mellem 20 og 60 - Alle HUNKØN i JYLLAND
Jeg har leget lidt med ideen om at lave en SQL sætning således: SELECT tableUsers.* FROM tableUsers WHERE idUser IN(SELECT ridUser FROM tableGenderToUsers WHERE idGender = 2 AND ridUser IN(SELECT ridUser FROM tableAreaToUsers WHERE idArea IN(1,2)))
Men det ser blot ud til at dette databaseopslag er enormt langsomt, og en explain sætning viser da også at det langt fra er effektivt...
There - undskyld den lange stil - og jeg håber der er nogle der kan / vil hjælpe! Tusind tak :)
Det er også sådan jeg normaltvis ville have gjort det, men eftersom jeg ikke kan lave et effektivt index på den opbygning (da man f.eks. i en søgning ikke ville vælge at idGender skal være noget bestemt), er den ikke helt god... Du skal forestille dig at der kan være 100.000 brugere f.eks., og 20 forskellige søge kriterier.. Så en alm. sætning uden indexes ville tage for lang tid at afvikle.
Ved ikke hvor kraftig din server er, men den opbygning du har, kan jeg ikke se er mere effektiv. Tvært imod... Databasen har dælme mange joins den skal styre.
Desuden burde en ganske normal select på +100k rækker tage max et par sek. Og skal idGender ikke være noget bestemt, undlades den bare fra where hvilket kun forøger søgetiden.
Med min opbygning ville søgningerne se sådan ud:
select * from tableUsers where idAge>10 and idAge<20 select * from tableUsers where idAge>10 and idAge<20 and idGender=1 select * from tableUsers where idAge>10 and idAge<20 and idGender=1 and idArea=3
Alle disse 3 select ville max tage et par sek at afvikle. Selv uden indexes.
ps. Jeg ville så have et par ekstra tabeller om indeholder en reference til idGender og idArea
Og tak for din uddybning - jeg er dog alligevel desværre nødt til at finde en anden løsning. Selvom det max tager et par sek. at lave det opslag som du skriver, så dur det ikke - fordi hvis der er 5-10 brugere der laver en søgning i sekundet, så er der et gevaldigt problem med database serveren (det er en dating-portal der er tale om).
Min opbygning er mere effektiv, hvis man tænker med i det at tableUsers bliver meget meget stor (muligvis 1-2GB), mens index tabellerne givetvis ville fylde max 1MB pr. stk da det blot er int's der skal søges iblandt...
Så ville jeg gerne, at den første finder de brugere der er i aldersgruppen (20 år) - dvs. nu er der måske 7.000 brugere. Så skal den blandt de brugere finde hunkøn - så er der måske 3.500 brugere tilbage. Og tilsidst de fra Fyn, hvilket måske efterlader 400 brugere.
Jeg vil så kunne slå op i users tabellen og hente disse 400 brugere ud.
Søgninger som denne kan som sagt ske 10 gange i sekundet, og derfor er det så vigtigt at SQL'en er afsindigt effektiv - for hvis jeg skal løbe hele users tabellen på 2-5GB igennem hver gang der laves en søgning, så går harddisken på database serveren i knæ...
select u.* from tableUsers u inner join tableAgeToUsers age on age.ridUser=u.idUser and age.idAge=20 inner join tableAreaToUsers area on area.ridUser=u.idUser and area.idArea=3 inner join tableGenderToUsers gen on gen.ridUser=u.idUser and gen.idGender=1
Jeg går ud fra at idArea og idGender er en ID-henvisning til en anden tabel.
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.