/ Forside / Teknologi / Udvikling / SQL / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
SQL
#NavnPoint
pmbruun 1704
niller 962
fehaar 730
Interkril.. 701
ellebye 510
pawel 510
rpje 405
pete 350
gibson 320
10  smorch 260
Pre-generering/cache af træ
Fra : Leif Neland


Dato : 24-10-08 09:24

Jeg skyder lidt med spredehagl, men har da sat fut...

Jeg har en menustruktur, der sjældent opdateres.

Den er opbygget klassisk, med en startnode, og hver node har en forælder, og
en rækkefølge til søskende.
Altså "select * from menu where parent = $parentid order by rank"
For at få hentet træet (Der forøvrigt åbnes og lukkes med javascript på
websiden), skal der rekursivt laves en masse kald fra webserver til
databasen.

Er der nogle gode ideer til at "compilere" træet, at lave en indexering
eller lignende, så træet kan hentes frem med en enkelt sql?
Et ekstra felt, der bruges til at sortere på?

Eller skulle man pre-generere menytræet til en html-fil, der inkluderes?

Det måtte også gerne optimere breadcrumbs, så man ikke rekursivt skulle søge
tilbage til forældre og for-forældre til man kommer til roden.

Det er ikke noget problem, at man fra admin-systemet skal køre "opdater
menutræ" efter der er lavet rettelser i træet.

Leif



 
 
Martin (24-10-2008)
Kommentar
Fra : Martin


Dato : 24-10-08 14:24

Leif Neland wrote:
> Jeg skyder lidt med spredehagl, men har da sat fut...
>
> Jeg har en menustruktur, der sjældent opdateres.
>
> Den er opbygget klassisk, med en startnode, og hver node har en forælder, og
> en rækkefølge til søskende.
> Altså "select * from menu where parent = $parentid order by rank"
> For at få hentet træet (Der forøvrigt åbnes og lukkes med javascript på
> websiden), skal der rekursivt laves en masse kald fra webserver til
> databasen.
>
> Er der nogle gode ideer til at "compilere" træet, at lave en indexering
> eller lignende, så træet kan hentes frem med en enkelt sql?
> Et ekstra felt, der bruges til at sortere på?
>
> Eller skulle man pre-generere menytræet til en html-fil, der inkluderes?
>
> Det måtte også gerne optimere breadcrumbs, så man ikke rekursivt skulle søge
> tilbage til forældre og for-forældre til man kommer til roden.
>
> Det er ikke noget problem, at man fra admin-systemet skal køre "opdater
> menutræ" efter der er lavet rettelser i træet.
>
> Leif
>
>

Man kan lave et sorteringsfelt.

Fx.
Level 1 i menuen har sorteringen
00000000001

Level 2
000000001 (2 nuller mindre end level 1)

Level 3
0000001 (4 nuller mindre end level 1)

Dette gør at der er plads til 99 menupunkter under hvert level og 6-7
levels.

SELECT * FROM menu ORDER BY levelsort

Så kan du også lige lave et ekstra felt, der fortæller hvilken level
menupunktet er en del af. Så kan man lave noget rimelig simpelt serverside.

Selvfølgelig er det kun noget jeg vil anbefale til "statiske" menuer,
altså menuer der ikke særlig tit bliver opdateret, da det kræver man
holder tungen lige i munden når man laver levelsort.

PS
Husk at MySQL automatisk cacher x antal mb af de queries du bruger mest,
så kan være du slet ikke behøver at gøre så meget.

Arne Vajhøj (24-10-2008)
Kommentar
Fra : Arne Vajhøj


Dato : 24-10-08 22:52

Leif Neland wrote:
> Jeg skyder lidt med spredehagl, men har da sat fut...
>
> Jeg har en menustruktur, der sjældent opdateres.
>
> Den er opbygget klassisk, med en startnode, og hver node har en forælder, og
> en rækkefølge til søskende.
> Altså "select * from menu where parent = $parentid order by rank"
> For at få hentet træet (Der forøvrigt åbnes og lukkes med javascript på
> websiden), skal der rekursivt laves en masse kald fra webserver til
> databasen.
>
> Er der nogle gode ideer til at "compilere" træet, at lave en indexering
> eller lignende, så træet kan hentes frem med en enkelt sql?
> Et ekstra felt, der bruges til at sortere på?
>
> Eller skulle man pre-generere menytræet til en html-fil, der inkluderes?
>
> Det måtte også gerne optimere breadcrumbs, så man ikke rekursivt skulle søge
> tilbage til forældre og for-forældre til man kommer til roden.
>
> Det er ikke noget problem, at man fra admin-systemet skal køre "opdater
> menutræ" efter der er lavet rettelser i træet.

Gem din menu struktur i form af XML som en enkelt værdi i
databasen.

Hvis din database understøtter stored procedures i et egnet
programmering sprog, så kan du sætter triggers på de bagved
liggende tabeller og felter, således at ved opdatering så
opdateres XML'en automatisk.

Ikke en speciel pæn løsning fra en ren database synsvinkel
men praktisk.

Arne

Stig Johansen (25-10-2008)
Kommentar
Fra : Stig Johansen


Dato : 25-10-08 04:31

Leif Neland wrote:

> Jeg skyder lidt med spredehagl, men har da sat fut...
>
> Jeg har en menustruktur, der sjældent opdateres.
>
> Den er opbygget klassisk, med en startnode, og hver node har en forælder,
> og en rækkefølge til søskende.
> Altså "select * from menu where parent = $parentid order by rank"
> For at få hentet træet (Der forøvrigt åbnes og lukkes med javascript på
> websiden), skal der rekursivt laves en masse kald fra webserver til
> databasen.

Ikke nødvendigvis (rekursivt).

> Er der nogle gode ideer til at "compilere" træet, at lave en indexering
> eller lignende, så træet kan hentes frem med en enkelt sql?

Hvis du laver lige så mange LEFT JOIN's som din 'depth' af træet, kan du
lave det i eet hug.
Hvis vi antager at din menu har en id, parentid, samt link, bliver det noget
a la:
SELECT m.link AS mlink, m1.link AS m1link, m2.link AS m2link ...
FROM menu m
LEFT JOIN menu m1 ON m1.parentid = m.id
LEFT JOIN menu m2 ON m2.parentid = m1.id
.... osv..
WHERE m.parentid=0
ORDER BY m,m1,m2..

Her går jeg ud fra 'mastermenu' har 0 i parentid.

> Et ekstra felt, der bruges til at sortere på?

Du skriver lidt om du har et rank felt, det må du lege lidt med af hensyn
til sorteringen.

Ovenstående metode har jeg brugt til generering af træer. Her skal der blot
et par if's til at tjekke en given record mod den foregående, der tjekker
om man skifter nodes indedn for tæet.

> Det måtte også gerne optimere breadcrumbs, så man ikke rekursivt skulle
> søge tilbage til forældre og for-forældre til man kommer til roden.

De vil være en del af ovennævnte udtræk.

--
Med venlig hilsen
Stig Johansen

Michael Zedeler (25-10-2008)
Kommentar
Fra : Michael Zedeler


Dato : 25-10-08 16:29

Leif Neland wrote:
> Jeg skyder lidt med spredehagl, men har da sat fut...
>
> Jeg har en menustruktur, der sjældent opdateres.
>
> Den er opbygget klassisk, med en startnode, og hver node har en forælder, og
> en rækkefølge til søskende.
> Altså "select * from menu where parent = $parentid order by rank"
> For at få hentet træet (Der forøvrigt åbnes og lukkes med javascript på
> websiden), skal der rekursivt laves en masse kald fra webserver til
> databasen.
>
> Er der nogle gode ideer til at "compilere" træet, at lave en indexering
> eller lignende, så træet kan hentes frem med en enkelt sql?

FUT: dk.edb.database

Ja. Der er en meget elegant måde hvor man med een forespørgsel kan hente
et undertræ, hvis man benytter et interval til at anføre hvor i træet,
den pågældende knude hører til.

Lad det maksimale interval være [0;100].

Roden har dette interval.

Hvis roden har fire undermenuer, får de følgende intervaller:

Undermenu 1: [0;24]
Undermenu 2: [25;49]
Undermenu 3: [50;74]
Undermenu 4: [75;100]

Hvis man vil putte undermenuer på niveau 2 under Undermenu 2 - antag at
der er to af dem - får de disse intervaller:

Under-undermenu 1: [25;37]
Under-undermenu 2: [38;49]

....og så fremdeles.

Antag at intervalgrænserne lagres som t_start og t_end i en tabel med
menupunkter. Hvis man nu ønsker at hive hele menuen ud i dybde først
rækkefølge, skal man bare bruge denne forespørgsel:

SELECT * FROM menu ORDER BY t_start

Ønsker man kun en undermenu (og dens børn) med intervallet [u_start;
u_end], føjer man et enkelt kriterie til:

SELECT * FROM menu
WHERE t_start <= u_start AND t_end >= u_end
ORDER BY t_start

Til opdatering af menupunkterne kan man godt lave nogle kløgtige
update-forespørgsler der flytter hele deltræer, hvis man løber tør for
plads.

Det smarte ved denne metode er at man ikke behøver at cache noget.
Ulempen er at opdateringer er lidt mere komplekse.

> Et ekstra felt, der bruges til at sortere på?

Rækkefølgen afgøres af t_start ovenfor. Ønsker man at bytte rækkefølgen
på to menupunkter, kan man blot lade dem bytte intervaller.

> Eller skulle man pre-generere menytræet til en html-fil, der inkluderes?
>
> Det måtte også gerne optimere breadcrumbs, så man ikke rekursivt skulle søge
> tilbage til forældre og for-forældre til man kommer til roden.

Det er også løst med denne metode. Man skal blot bytte om på parametrene
i forespørgslen ovenfor.

Der er skrevet en artikel om den metode, jeg beskriver her, men desværre
kan jeg ikke finde den. Hvis nogen er meget interesserede, vil jeg gerne
gøre et ekstra forsøg på at fiske den frem.

Mvh. Michael.

Jørn Andersen (25-10-2008)
Kommentar
Fra : Jørn Andersen


Dato : 25-10-08 22:54

On Fri, 24 Oct 2008 10:24:07 +0200, "Leif Neland" <leif@neland.dk>
wrote:

>Jeg har en menustruktur, der sjældent opdateres.
>
>Den er opbygget klassisk, med en startnode, og hver node har en forælder, og
>en rækkefølge til søskende.
>Altså "select * from menu where parent = $parentid order by rank"
>For at få hentet træet (Der forøvrigt åbnes og lukkes med javascript på
>websiden), skal der rekursivt laves en masse kald fra webserver til
>databasen.

Hvis ASP (måske det samme i PHP, som jeg ikke kender ret godt?):
Kan du ikke hente det hele over i et array med objRs.GetRows og så køre
den rekursive på arrayet - det burde være noget hurtigere.

<snip>

>Eller skulle man pre-generere menytræet til en html-fil, der inkluderes?

Hvis den sjældent ændres, så er det nok det enkleste.


Mvh. Jørn

--
Jørn Andersen,
Brønshøj

Søg
Reklame
Statistik
Spørgsmål : 177428
Tips : 31962
Nyheder : 719565
Indlæg : 6407944
Brugere : 218877

Månedens bedste
Årets bedste
Sidste års bedste