Ik ben bezig met het (her-)schrijven van wat ik mijn 'hypertree' noem. Kort gezegd is het een soort boomstructuur waarbij elke 'node' niet alleen meedere 'childnodes' kan hebben, maar ook meerdere 'parentnodes'. Bijbehorende (SQL-) databasestructuur bevat aldus een node tabel (id, name) en een relation tabel (id, parent_id, child_id).
Nu vraag ik mij af of het de moeite waard is om in de node tabel eveneens de volgende -ik neem aan voor zichzelf sprekende- velden op moet nemen: parent_count, child_count, of dat ik het aantal relaties van een node beter gewoon op kan zoeken in de relation tabel wanneer het nodig is.
Het grootste voordeel wat ik eruit haal, is dat het me behoorlijk wat SELECTS kan schelen wanneer ik de boom uitlees (hoef niet te kijken of een node children/nog meer parents heeft), of wanneer ik bijvoorbeeld nodes delete, ik meteen weet of de node toevallig ook nog onder een andere parent hangt (zodat ik kan bepalen of ik ook echt "DELETE FROM node ..." moet doen of slechts een relation moet DELETEen).
Het nadeel is dat het een "bitch" is om die counts netjes bij te houden: Bij elke "reference-", "move-", "delete-" node(s) bewerking aan de boom zal ik 1 of 2 UPDATEs moeten doen aan de node tabel*, terwijl ik anders slechts 1 keer hoef te INSERTen, UPDATEn of DELETEn in de relation tabel.
Ik ben van start gegaan met de extra velden voor de referentie-counts. Momenteel ben ik een behoorlijk eind gevorderd met het coden van de functies voor het "referencen", "moven" en "deleten/dereferencen" van nodes en selecties van nodes. Het uitlezen werkt al lang goed, maar is nog niet geoptimailseerd m.b.t het beperken van SELECTs.
Mijn vragen hieromtrent:
1. Hoe werken jullie in soortgelijke situaties? Of wat lijkt je het beste?
2. Kan ik mijn SELECTs uit de relation tabel evt. sneller maken door bv. "LIMIT node.child_count" te doen? (Dit als eventuele toevoeging op de echte winst die ik haal bij het helemaal niet zoeken naar parents/children wanneer de refcounts ervan op 0 staan)
3. Ben ik eigenlijk verplicht om gebruik te gaan maken van transaction-enabled databasetables, om te voorkomen dat er incongruentie onstaat tussen het daadwerkelijke aantal relaties en de bijgehouden aantallen, wanneer er bijvoorbeeld halverwege een bewerkingsactie iets misgaat of er een andere user tussendoor gaat rommelen?**
* voor het UPDATEn van de ref-counts gebruik ik relatieve waarden ("UPDATE node SET child_count = child_count + $x ...", waarbij ik $x gelijk is aan het aantal geselecteerde nodes, die ik via een sessie-variabele verkrijg, m.a.w. geen SELECT voor nodig.
** voor zover ik m'n eigen code en database begrijp, kan er in principe weinig misgaan. stel: 2 users besluiten tegelijkertijd een node naar elk een andere parent te moven. Bij zo'n actie hoef ik alleen een relation.parent_id te veranderen, de parent_count verandert in dat geval niet van de te verplaatsen node, alleen de child_counts van de betrokken parent_nodes. Eén zo'n actie verloopt als volgt:
ik weet niet eens of het mogelijk is, maar ik ga even van het feit uit dat deze opeenvolging van queries wanneer twee users ze tegelijk uitvoeren zodanig is, dat de 2 eersten uit de serie van 3 exact na elkaar gescheduled worden. Die van de 2e user geeft aldus 0 affected rows terug. Waarop ik dus weet dat er iemand anders ook aan het 'moven' is. Dus maak ik gewoon een extra relatie aan ipv die laatste 2 updates:
die SELECT zit er omheen om te checken of beide users niet toevallig dezelfde nieuwe parent node hebben gekozen, indat geval blazen we actie van user 2 gewoon helemaal af en heft ie hetzelfde resultaat.
Dit lijkt me dus allemaal goed te gaan, maar het begint me allemaal een beetje te duizelen als ik weet dat users ook meerdere nodes (op 1 niveau) kunnen selecteren en daarmee kunnen gaan moven, referencen, deleten, etcetera. Lastiger wordt het bijvoorbeeld wanneer 2 users tegelijkertijd besluiten dezelfde node, die bij de ene user-view onder een andere parent hangt dan bij de andere user-view, te "unlinken", elk in de veronderstelling dat de node niet verloren gaat omdat ie toch nog wel onder de andere hangt. Dan kan ik prutsen wat ik wil, maar de node gaat hoe dan ook verloren!
Of moet ik het gewoon niet toestaan dat 2 users op hetzelfde niveau bepaalde acties uitvoeren (geselecteerde nodes in een temp table bijhouden?)
gekkenhuis in mijn hoofd, geeft niet als dit als complete nonsense overkomt, ik heb zelf al een beetje meer inzicht in de problematiek door het op te hebben geschreven...
[edit]
goh wat kan een stukje fietsen goed helpen...weg met die counts! het is al pittig genoeg zonder die krengen...al die UPDATEs wegen bij nader inzien niet echt op tegen die eventuele lege SELECTies die ik af en toe moet doen. of zijn er toch mensen die dit wel met succes toepassen?
Nu vraag ik mij af of het de moeite waard is om in de node tabel eveneens de volgende -ik neem aan voor zichzelf sprekende- velden op moet nemen: parent_count, child_count, of dat ik het aantal relaties van een node beter gewoon op kan zoeken in de relation tabel wanneer het nodig is.
Het grootste voordeel wat ik eruit haal, is dat het me behoorlijk wat SELECTS kan schelen wanneer ik de boom uitlees (hoef niet te kijken of een node children/nog meer parents heeft), of wanneer ik bijvoorbeeld nodes delete, ik meteen weet of de node toevallig ook nog onder een andere parent hangt (zodat ik kan bepalen of ik ook echt "DELETE FROM node ..." moet doen of slechts een relation moet DELETEen).
Het nadeel is dat het een "bitch" is om die counts netjes bij te houden: Bij elke "reference-", "move-", "delete-" node(s) bewerking aan de boom zal ik 1 of 2 UPDATEs moeten doen aan de node tabel*, terwijl ik anders slechts 1 keer hoef te INSERTen, UPDATEn of DELETEn in de relation tabel.
Ik ben van start gegaan met de extra velden voor de referentie-counts. Momenteel ben ik een behoorlijk eind gevorderd met het coden van de functies voor het "referencen", "moven" en "deleten/dereferencen" van nodes en selecties van nodes. Het uitlezen werkt al lang goed, maar is nog niet geoptimailseerd m.b.t het beperken van SELECTs.
Mijn vragen hieromtrent:
1. Hoe werken jullie in soortgelijke situaties? Of wat lijkt je het beste?
2. Kan ik mijn SELECTs uit de relation tabel evt. sneller maken door bv. "LIMIT node.child_count" te doen? (Dit als eventuele toevoeging op de echte winst die ik haal bij het helemaal niet zoeken naar parents/children wanneer de refcounts ervan op 0 staan)
3. Ben ik eigenlijk verplicht om gebruik te gaan maken van transaction-enabled databasetables, om te voorkomen dat er incongruentie onstaat tussen het daadwerkelijke aantal relaties en de bijgehouden aantallen, wanneer er bijvoorbeeld halverwege een bewerkingsactie iets misgaat of er een andere user tussendoor gaat rommelen?**
* voor het UPDATEn van de ref-counts gebruik ik relatieve waarden ("UPDATE node SET child_count = child_count + $x ...", waarbij ik $x gelijk is aan het aantal geselecteerde nodes, die ik via een sessie-variabele verkrijg, m.a.w. geen SELECT voor nodig.
** voor zover ik m'n eigen code en database begrijp, kan er in principe weinig misgaan. stel: 2 users besluiten tegelijkertijd een node naar elk een andere parent te moven. Bij zo'n actie hoef ik alleen een relation.parent_id te veranderen, de parent_count verandert in dat geval niet van de te verplaatsen node, alleen de child_counts van de betrokken parent_nodes. Eén zo'n actie verloopt als volgt:
code:
1
2
3
4
| ($x $y en $z zijn user-input via sessievars) UPDATE relation SET parent_id = $z WHERE parent_id = $x AND child_id = $y; UPDATE node SET child_count-- WHERE id = $x; van de oude parent UPDATE node SET child_count++ WHERE id = $z; van de nieuwe parent. |
ik weet niet eens of het mogelijk is, maar ik ga even van het feit uit dat deze opeenvolging van queries wanneer twee users ze tegelijk uitvoeren zodanig is, dat de 2 eersten uit de serie van 3 exact na elkaar gescheduled worden. Die van de 2e user geeft aldus 0 affected rows terug. Waarop ik dus weet dat er iemand anders ook aan het 'moven' is. Dus maak ik gewoon een extra relatie aan ipv die laatste 2 updates:
code:
1
2
3
4
5
6
7
| SELECT FROM relation WHERE parent_id = $z AND child_id =$y;
if (0 rows terug)
{
INSERT INTO relation (parent_id, child_id) VALUES ($z, $y);
UPDATE node SET parent_count++ WHERE id = $y;
UPDATE node SET child_count++ WHERE id = $z;
} |
die SELECT zit er omheen om te checken of beide users niet toevallig dezelfde nieuwe parent node hebben gekozen, indat geval blazen we actie van user 2 gewoon helemaal af en heft ie hetzelfde resultaat.
Dit lijkt me dus allemaal goed te gaan, maar het begint me allemaal een beetje te duizelen als ik weet dat users ook meerdere nodes (op 1 niveau) kunnen selecteren en daarmee kunnen gaan moven, referencen, deleten, etcetera. Lastiger wordt het bijvoorbeeld wanneer 2 users tegelijkertijd besluiten dezelfde node, die bij de ene user-view onder een andere parent hangt dan bij de andere user-view, te "unlinken", elk in de veronderstelling dat de node niet verloren gaat omdat ie toch nog wel onder de andere hangt. Dan kan ik prutsen wat ik wil, maar de node gaat hoe dan ook verloren!
Of moet ik het gewoon niet toestaan dat 2 users op hetzelfde niveau bepaalde acties uitvoeren (geselecteerde nodes in een temp table bijhouden?)
gekkenhuis in mijn hoofd, geeft niet als dit als complete nonsense overkomt, ik heb zelf al een beetje meer inzicht in de problematiek door het op te hebben geschreven...
[edit]
goh wat kan een stukje fietsen goed helpen...weg met die counts! het is al pittig genoeg zonder die krengen...al die UPDATEs wegen bij nader inzien niet echt op tegen die eventuele lege SELECTies die ik af en toe moet doen. of zijn er toch mensen die dit wel met succes toepassen?
[ Voor 11% gewijzigd door Genoil op 11-02-2003 03:52 ]