nested sets und verschiebeaktionen

nested sets und verschiebeaktionen

am 02.07.2005 13:26:03 von Martin Klaffenboeck

Hallo!

Ich versuche nun in nested sets Verschiebeaktionen durchzuführen.

Dabei bräuchte ich die Möglichkeit mehrere Queries gleichzeitig
durchzuführen - geht das?

damit meine ich z.B. wenn ich einen subbaum nach oben (neben den parent)
verschieben will, so muss ich folgende 2 updates durchführen:

{..} - sind zuvor errechnete Werte

Vor den updates muss gesagt werden, das {LEFT,RIGHT} und
{OTHERLEFT,OTHERRIGHT} zwei unabhängige mengen sind und keine gemeinsamen
Items besitzen.

update tabelle
set L = L + {MOVE}
set R = R + {MOVE}
where L >= {LEFT} and R <= {RIGHT}

2)
update tabelle
set L = L - {DIFF}
set R = R - {DIFF}
where L >= {OTHERLEFT} and R <= {OTHERRIGHT}

nun habe ich folgendes Dilemma:

Führe ich update 1 zuerst durch, so haben einige L's bzw. R's werte die
bei der where Klausel von update 2 reinfallen. Und führe ich zuerst
update 2 durch, so bekommen diese items werte die dann von der where
Klausel des updates 1 reinfallen. Ich würde daher gerne so in der art
zuerst die beiden where klausels durchlaufen, so dass mysql weiß welche
items gemeint sind und dann die updates durchführen, so dass die nicht
gemeinten nicht zweimal upgedatet werden.

Geht das irgendwie?

Dankeschön,
Martin

Re: nested sets und verschiebeaktionen

am 02.07.2005 13:50:38 von Stefan Rybacki

Martin Klaffenboeck wrote:
> Hallo!
>
> Ich versuche nun in nested sets Verschiebeaktionen durchzuführen.
>
> Dabei bräuchte ich die Möglichkeit mehrere Queries gleichzeitig
> durchzuführen - geht das?
>
> damit meine ich z.B. wenn ich einen subbaum nach oben (neben den parent)
> verschieben will, so muss ich folgende 2 updates durchführen:
>
> {..} - sind zuvor errechnete Werte
>
> Vor den updates muss gesagt werden, das {LEFT,RIGHT} und
> {OTHERLEFT,OTHERRIGHT} zwei unabhängige mengen sind und keine gemeinsamen
> Items besitzen.
>
> update tabelle
> set L = L + {MOVE}
> set R = R + {MOVE}
> where L >= {LEFT} and R <= {RIGHT}
>
> 2)
> update tabelle
> set L = L - {DIFF}
> set R = R - {DIFF}
> where L >= {OTHERLEFT} and R <= {OTHERRIGHT}
>
> nun habe ich folgendes Dilemma:
>
> Führe ich update 1 zuerst durch, so haben einige L's bzw. R's werte die
> bei der where Klausel von update 2 reinfallen. Und führe ich zuerst
> update 2 durch, so bekommen diese items werte die dann von der where
> Klausel des updates 1 reinfallen. Ich würde daher gerne so in der art
> zuerst die beiden where klausels durchlaufen, so dass mysql weiß welche
> items gemeint sind und dann die updates durchführen, so dass die nicht
> gemeinten nicht zweimal upgedatet werden.
>
> Geht das irgendwie?


Wie wäre es mit einem zusätzlichen Attribut, das speichert, ob bereits
ein Update vorgenommen wurde?

Bis denn dann
Stefan

>
> Dankeschön,
> Martin

Re: nested sets und verschiebeaktionen

am 02.07.2005 14:16:19 von Timo Kissing

Martin Klaffenboeck meinte:

> Hallo!
>
> Ich versuche nun in nested sets Verschiebeaktionen durchzuführen.
>
> Dabei bräuchte ich die Möglichkeit mehrere Queries gleichzeitig
> durchzuführen - geht das?
>
> damit meine ich z.B. wenn ich einen subbaum nach oben (neben den parent)
> verschieben will, so muss ich folgende 2 updates durchführen:
>
> {..} - sind zuvor errechnete Werte
>
> Vor den updates muss gesagt werden, das {LEFT,RIGHT} und
> {OTHERLEFT,OTHERRIGHT} zwei unabhängige mengen sind und keine gemeinsamen
> Items besitzen.
>
> update tabelle
> set L = L + {MOVE}
> set R = R + {MOVE}
> where L >= {LEFT} and R <= {RIGHT}
>
> 2)
> update tabelle
> set L = L - {DIFF}
> set R = R - {DIFF}
> where L >= {OTHERLEFT} and R <= {OTHERRIGHT}
>
> nun habe ich folgendes Dilemma:
>
> Führe ich update 1 zuerst durch, so haben einige L's bzw. R's werte die
> bei der where Klausel von update 2 reinfallen. Und führe ich zuerst
> update 2 durch, so bekommen diese items werte die dann von der where
> Klausel des updates 1 reinfallen. Ich würde daher gerne so in der art
> zuerst die beiden where klausels durchlaufen, so dass mysql weiß welche
> items gemeint sind und dann die updates durchführen, so dass die nicht
> gemeinten nicht zweimal upgedatet werden.
>
> Geht das irgendwie?

Also mir ist keine Möglichkeit bekannt (und ich hab eifrig danach
gegoogelt, als ich das vor kurzem selber mal brauchte), mit der du einen
Teilbaum verschieben kannst, ohne den Zwischenzuspeichern. Du musst also
entweder eine temporäre Tabelle anlegen, den Teilbaum dadrin speichern, ihn
aus dem Baum entfernen und dann (auf gewohnte Weise) in den resultierenden
Baum einfügen - oder du speicherst ihn in ausserhalb von MySQL zwischen
(ich hol mir den zB in ein php-Array) und fügst ihn nach dem löschen von
dort aus wieder ein.

Falls jemand doch noch eine reine SQL-Lösung ohne zwischenspeichern kennt,
ich würd mich sehr freuen die zu hören.

lino
--
°° Oberster Verteidiger des Ordens der Dunklen Seite von de.ALL [tm] °°
Rule One: Do not act incautiously when confronting little bald
wrinkly smiling men.
Rule Two: Never refuse a weapon.

Re: nested sets und verschiebeaktionen

am 02.07.2005 15:18:09 von Christoph Reeg

Timo Kissing <2005-07@ranta.info> writes:

Hallo,

> Falls jemand doch noch eine reine SQL-Lösung ohne zwischenspeichern kennt,
> ich würd mich sehr freuen die zu hören.

eine andere Form von Zwischenspeichern: "Hinter" den Baum
verschieben. Also die L und R Werte einfach +10000 (wenn der Baum max
5000 Elemente hat).

Das Verschieben habe ich in 3 Schritten gelöst:
1. An der neuen Stelle Platz machen (also alle L und R rechts von der
gewünschten Stelle um 2*(Anzahl Elemente im Teilbaum erhöhen)
2. Den Teilbaum dorthin verschieben
3. Die Lücke an der alten Stelle wieder schließen

Das ganze geht mit 5 Updates und 3(?) Select.


HTH,
Christoph

--
Christoph Reeg (http://reeg.net/)
Wenn ich eine SuSE-CD an ein Schwein binde und dieses trete, laufen
KDE & Co. auch ohne RAM recht schnell.
-- Robin S. Socha in de.comp.os.unix.linux.newusers

Re: nested sets und verschiebeaktionen

am 02.07.2005 15:53:43 von Stefan Rybacki

Christoph Reeg wrote:
> Timo Kissing <2005-07@ranta.info> writes:
>
> Hallo,
>
>
>>Falls jemand doch noch eine reine SQL-Lösung ohne zwischenspeichern kennt,
>>ich würd mich sehr freuen die zu hören.
>
>
> eine andere Form von Zwischenspeichern: "Hinter" den Baum
> verschieben. Also die L und R Werte einfach +10000 (wenn der Baum max
> 5000 Elemente hat).
>
> Das Verschieben habe ich in 3 Schritten gelöst:
> 1. An der neuen Stelle Platz machen (also alle L und R rechts von der
> gewünschten Stelle um 2*(Anzahl Elemente im Teilbaum erhöhen)
> 2. Den Teilbaum dorthin verschieben
> 3. Die Lücke an der alten Stelle wieder schließen
>
> Das ganze geht mit 5 Updates und 3(?) Select.
>
>
> HTH,
> Christoph
>

Was spricht denn gegen ein zusätzliches Attribut?

//lock tabelle fürs Schreiben

update tabelle
set updated=0

update tabelle
set L = L + {MOVE}
set R = R + {MOVE}
set updated=1
where L >= {LEFT} and R <= {RIGHT}

2)
update tabelle
set L = L - {DIFF}
set R = R - {DIFF}
where L >= {OTHERLEFT} and R <= {OTHERRIGHT} and updated=0


Bis denn dann
Stefan

Re: nested sets und verschiebeaktionen

am 02.07.2005 17:08:10 von Martin Klaffenboeck

Am Sat, 02 Jul 2005 13:50:38 +0200 schrieb Stefan Rybacki:

>
> Wie wäre es mit einem zusätzlichen Attribut, das speichert, ob bereits
> ein Update vorgenommen wurde?

Das ist mir auch schon in den Sinn gekommen. Ich könnte aber auch die
Idee mit +10000 ansehen. Ich kann ja vom Root item sehen wie hoch die
Zahl mindestens sein muss. Dann kommt man ja letzlich mit 3 updates aus.

Aber mir scheint das alles noch nicht so sinnvoll zu sein. Ich denke,
dass es eigentlich eine übliche vorgehensweise sein müsste, weil es ja
durchaus vorkommen kann, dass man auch beim primary key, z.b. einfach nur
2 Items vertauschen möchte. Wozu der Umweg?

Ich könnte ja auch mit einem select zuvor die ID's aller zu
verschiebenden Items rausfinden, dann das 'Loch' das es noch nicht gibt
schließen und dann ein update auf where ID=... or ID= or ID= .. vom
programm erstellen lassen.

Das wäre meine Notlösung.

lg,
Martin

Re: nested sets und verschiebeaktionen

am 04.07.2005 11:19:39 von Harald Stowasser

Martin Klaffenboeck schrieb:


> Dabei bräuchte ich die Möglichkeit mehrere Queries gleichzeitig
> durchzuführen - geht das?

Nein!
[...]

> nun habe ich folgendes Dilemma:
>
> Führe ich update 1 zuerst durch, so haben einige L's bzw. R's werte die
> bei der where Klausel von update 2 reinfallen. Und führe ich zuerst
> update 2 durch, so bekommen diese items werte die dann von der where
> Klausel des updates 1 reinfallen. Ich würde daher gerne so in der art
> zuerst die beiden where klausels durchlaufen, so dass mysql weiß welche
> items gemeint sind und dann die updates durchführen, so dass die nicht
> gemeinten nicht zweimal upgedatet werden.
>
> Geht das irgendwie?

Am besten arbytest du mit einer Zwischentabelle.
Ich habe mal ein Beispiel in [1]
gepostet.


[1]http://groups.google.de/group/de.comp.datenbanken.mysql/m sg/a68f45bba1f53158

Re: nested sets und verschiebeaktionen

am 04.07.2005 16:34:33 von Martin Klaffenboeck

Am Mon, 04 Jul 2005 11:19:39 +0200 schrieb Harald Stowasser:

> Am besten arbytest du mit einer Zwischentabelle.
> Ich habe mal ein Beispiel in [1]
> gepostet.
>
>
> [1]http://groups.google.de/group/de.comp.datenbanken.mysql/m sg/a68f45bba1f53158

Ja, daran habe ich auch schon gedacht. Ich weiß aber nicht so recht ob
ich das jetzt doch mit einem eigenen 'Selected' Feld mache, welches zuerst
alle zu verschiebenden markiert (anstatt in die temporäre Tabelle zu
verschieben) dann das loch schließen (dann stimmen bei den markierten die
Lefts und Rights nicht mehr, die werden dann noch angepasst und selected
auf NULL gesetzt.

Müsste eigentlich schneller sein, weil ich denke, dass da keine Einträge
verschoben werden. Allerdings weiß ich nicht, wie weit bei temporären
tabellen tatsächlich verschoben wird.

Es ist halt so, dass in meiner Tabelle letztlich auch lange Texte sich
befinden. Diese müssten dann zweimal verschoben werden, wenn ich den
ganzen Datensatz verschiebe. Ansonsten müssen ja nur updates gemacht
werden.

Was genau macht eigentlich select for update? Kann man damit nicht
vielleicht auch einzelne Datensätze markieren?

lg,
Martin

Re: nested sets und verschiebeaktionen

am 04.07.2005 18:37:19 von Kris

Martin Klaffenboeck wrote:
> Müsste eigentlich schneller sein, weil ich denke, dass da keine Einträge
> verschoben werden. Allerdings weiß ich nicht, wie weit bei temporären
> tabellen tatsächlich verschoben wird.

Richte Deine temporäre Tabelle als HEAP-Tabelle ein. Dann liegt sie im RAM.

> Was genau macht eigentlich select for update? Kann man damit nicht
> vielleicht auch einzelne Datensätze markieren?

Es erzeugt in Tabellen vom Typ Innodb Row-Locks (und zwar exklusive
Schreib-Locks). Jede andere Session, die versucht, diese Zeilen anzufassen,
hängt bis Du Deine Transaktion beendest und damit die Locks aufgibst.

Das Pedant zu "FOR UPDATE" wäre "LOCK IN SHARED MODE". Es erzeugt ebenfalls
Row-Locks, aber zum Lesen (stattdessen könnte man auch einfach den
Isolation Level hochdrehen).

Kristian

Re: nested sets und verschiebeaktionen

am 04.07.2005 19:35:32 von Martin Klaffenboeck

Am Mon, 04 Jul 2005 18:37:19 +0200 schrieb Kristian Köhntopp:

> Martin Klaffenboeck wrote:
>> Müsste eigentlich schneller sein, weil ich denke, dass da keine Einträge
>> verschoben werden. Allerdings weiß ich nicht, wie weit bei temporären
>> tabellen tatsächlich verschoben wird.
>
> Richte Deine temporäre Tabelle als HEAP-Tabelle ein. Dann liegt sie im RAM.

Ok, kann ich eine temporäre HEAP tabelle einfach mit den selben Felder
erzeugen, die die selben felder hat.

Gibts sowas wie create table temp_heap like mytable?

Ich denke, wenn das Performant ist, dann werde ich das so versuchen.

lg,
Martin

Re: nested sets und verschiebeaktionen

am 04.07.2005 19:47:03 von Martin Klaffenboeck

Am Mon, 04 Jul 2005 19:35:32 +0200 schrieb Martin Klaffenboeck:

> Am Mon, 04 Jul 2005 18:37:19 +0200 schrieb Kristian Köhntopp:
>
>> Martin Klaffenboeck wrote:
>>> Müsste eigentlich schneller sein, weil ich denke, dass da keine Einträge
>>> verschoben werden. Allerdings weiß ich nicht, wie weit bei temporären
>>> tabellen tatsächlich verschoben wird.
>>
>> Richte Deine temporäre Tabelle als HEAP-Tabelle ein. Dann liegt sie im RAM.
>
> Ok, kann ich eine temporäre HEAP tabelle einfach mit den selben Felder
> erzeugen, die die selben felder hat.
>
> Gibts sowas wie create table temp_heap like mytable?

Hum. Erst ab 4.1 Ich hab am Zielserver einen leider nicht für mich
greifbaren 4.0.19 mysql Server.

Mal sehen wie ich das dann mache. Schließlich kann ich ja nicht meine
Scripten umschreiben, wenn ich mal ein Feld in der Tabelle hinzufügen
möchte.

lg,
Martin

Re: nested sets und verschiebeaktionen

am 04.07.2005 20:02:09 von Harald Fuchs

In article ,
Kristian =3D?UTF-8?B?S8O2aG50b3Bw?=3D writes:

> Richte Deine temporäre Tabelle als HEAP-Tabelle ein. Dann liegt sie im =
RAM.

Hast Du zu dem Thema irgendwelche Messungen? Ich glaube, mich
erinnern zu können, daß HEAP in der Praxis kaum was bringt, weil
MySQL sowieso viel im RAM erledigt.

> Das Pedant zu "FOR UPDATE" wäre "LOCK IN SHARED MODE".


Das heißt "Pendant". "Pedant" ist das, was ich hier mache :-)

Re: nested sets und verschiebeaktionen

am 07.07.2005 17:11:13 von Frank Arthur

Martin Klaffenboeck schrieb:

> Ich versuche nun in nested sets Verschiebeaktionen durchzuführen.

Ich arbeite auch gerade an Lösungen im Nested Sets. Das Verschieben
von Teilbäumen habe ich noch nicht implementiert. Meine Nested Sets
(und deine sicher auch) haben eine root_id. Den Teilbaum kann man
einfach aus dem Nested Set entfernen, indem man die root_id des
Teilbaums auf 0 setzt. Dann wird die Lück entweder geschlossen oder
die nodes bis zur Lücke verschoben, dann der Teilbaum mit root_id = 0
wieder eingefügt (und root_id wieder zurücksetzen). Wie gesagt ich
habe das noch nicht implementiert, müsste aber gehen.

Re: nested sets und verschiebeaktionen

am 08.07.2005 09:25:40 von Martin Klaffenboeck

Am Thu, 07 Jul 2005 17:11:13 +0200 schrieb Frank Arthur:

> Martin Klaffenboeck schrieb:
>
>> Ich versuche nun in nested sets Verschiebeaktionen durchzuführen.
>
> Ich arbeite auch gerade an Lösungen im Nested Sets. Das Verschieben
> von Teilbäumen habe ich noch nicht implementiert. Meine Nested Sets
> (und deine sicher auch) haben eine root_id. Den Teilbaum kann man
> einfach aus dem Nested Set entfernen, indem man die root_id des
> Teilbaums auf 0 setzt. Dann wird die Lück entweder geschlossen oder
> die nodes bis zur Lücke verschoben, dann der Teilbaum mit root_id = 0
> wieder eingefügt (und root_id wieder zurücksetzen). Wie gesagt ich
> habe das noch nicht implementiert, müsste aber gehen.

Das ist eine hervorragende Idee!

BTW: In welche Sprache implementierst du? Vielleicht können wir ja was
gemeinsam machen?

lg,
Martin

Re: nested sets und verschiebeaktionen

am 09.07.2005 10:32:11 von Frank Arthur

Martin Klaffenboeck schrieb:


> BTW: In welche Sprache implementierst du? Vielleicht können wir ja was
> gemeinsam machen?

PHP.

Das wollen wir hier mal lieber nicht zu privat werden lassen, ich habe
dir an deine im header angegebene EMail adresse geschrieben.

tschau Frank.