Konzept-> optimierung (mySql)

tach community…

tu mich noch ein wenig schwer mit objektorientiertheit…
folgende aufgabe moechte optimiert werden:

es geht um memberbereiche. beispiel: user A darf nur seiten 3,4 und 6 sehen… user B darf alle sehen und user C nur seite 7

der user logged sich ein… und sieht seine loginpage (eine seite fuer alle gleich) auf der tabellarisch die seiten als links aufgelistet sind, auf die er zugriff hat.

bisher habe ich das so geloest, dass ich in der usertable (mysql) user ein feld mit komma separierten zahlen angelegt habe…
also

**USER ACCESS**
A 3,4,6
B 1,2,3,4,5,6,7
C 7

dann hab ich auf der ersten userseite (die mit den links) alle seiten praktisch bedingungsweise mit abfrage des arrays inkludiert…

also…schematisch —>

for(anzahl seiten;i++){
 if array($access==$i){
 echo('link zu seite'.$i.'.html');
 }
 i++;
}

bzw… habe es optimiert mit ner for-schleife auf die anzahl der seiten (steht auch in der DB)

allerdings ist das nicht besonders performant.

vor allem sehe ich probleme, da ich die tabellezeilen gerne sortieren koenenn moechte… und so wie ich das jetzt umgesetzt habe…ist das quatsch…

kann man das nicht irgendwie anders machen? brauche mal eine gedankenstuetze…

ich moechte also einfach nur eine liste der erlaubten seiten zeigen, die einem user zugeordnet sind…

wer-weiss-das?

grusz und danke

PixelKoenig

Hallo,

Also ich weiß nicht ob ich dich richtig verstanden habe und bin schon
gar kein Experte in mySQl, aber immerhin „Optimierer“ :wink:!

Ich würde es so machen:

Nummerier deine Seiten nicht 1,2,3,4,5,6,7…
sondern 2,3,5,7,11… also nach Primzahlen:

Das tolle daran ist:

jetzt ist die Zahl 385 EINDEUTIG den Seiten 5,7 und 11 zugeordnet,

da 5*7*11 die Primfaktorzerlegung von 385 ist.

Je nach Anzahl der Seiten brauchst du dann nur eine Methode
schreiben, die dir die Primfaktorzerlegung ausrechnet, oder bei
wenigen Seiten kannst du das auch in einer Tabelle speichern.
Dann brauchst du jedem User nur eine Zahl zuordnen und dir die
Schleife sparen!

Ciao Qasi

klingt doch gut…?
vorab wäre mal interessant wieviele Links es denn geben soll… Bei einer so geringen Anzahl sehe ich aber kein Problem bei der Performance - das sollte eigentlich erst bei ca 1000 Einträgen auch nur annähernd etwas ausmachen… Aber selbst das würde denke ich für den User nicht spürbar werden…

Aber um Dir ein paar Gedankenstützen zu geben mach ich hier einfach auch mal brainstorming :wink:
Warum nicht folgendermassen: Mach Dir eine zweite Tabelle…
Darin dann ein Aufbau wie folgt:
id link linktitel berechtigungen (datum?)
Deine Usertabelle wird dann einfach so umgeformt dass ein user und eine user-id drin steht… Am besten aber eine die sich aus Text und Nummer zusammen setzt… Sonst gibts evtl Probs bei niedrigen id’s :wink:
ok… dann machst Du folgendes - der User ist eingeloggt und Du hast Seine id in einer Variable…
Nun selektierst Du einfach alle Spalten, in denen dieser User eingetragen ist und gibst sie aus…

$query = mysql\_query("select link, linktitel from $tabellenname WHERE berechtigungen LIKE '%$userid%' ( **ORDER BY linktitel/id/datum... ASC**");
while ($result=mysql\_fetch\_array($query)
{
echo "link zu $result[link] mit linktitel";
}

Vorteil davon ist dass sowohl Dein Sortierproblem gelöst ist als auch dein „Problem“, dass die nicht benötigten einfach nur „ausgeblendet“ werden… Ein weiterer Vorteil ist aber, dass Du nicht diese link$i.html’s verwenden musst, was es urlhacks sehr sehr leich machen würde :wink:
Eine andere Methode mit der ich gerne arbeite sind accesslevel, aber das kommt bei Dir nicht in Frage, weil C was ganz anderes sehen darf als A…

Hilft Dir das weiter? :wink:

Hi Qasi,

ich möchte es mal so formulieren: Idee mathematisch in Ordnung (cool, würde ich sagen), aber informatisch ein Albtraum.

Je nach Anzahl der Seiten brauchst du dann nur eine Methode
schreiben, die dir die Primfaktorzerlegung ausrechnet,

Zwei Probleme: Erstens ist Primfaktorzerlegung ein nicht-triviales Problem, das eine erhebliche Komplexität hat (ich vermute NP-Vollständigkeit) – so gesehen hat das mit „Optimierung“ (= Komplexität reduzieren) gar nichts mehr zu tun.
Zweitens brauchst du für 100 Seiten 100 paarweise verschiedene Primzahlen, deren Produkt sich dann nicht mehr in einem normalen Integer speichern läßt. Der Ansatz stirbt also, wennn das Produkt aller „Seiten“ 4e9 übersteigt (unsigned long), und das ist schon nach

2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 = 223092870

der Fall. Mit der Methode kannst du also nur 9 Seiten speichern.

Die andere Idee finde ich prima.

Chris

Hallo Christian,

Zwei Probleme: Erstens ist Primfaktorzerlegung ein
nicht-triviales Problem, das eine erhebliche Komplexität hat
(ich vermute NP-Vollständigkeit) – so gesehen hat das mit

hmmm, ja die Koplexität dieser Methode ist natürlich sehr hoch, wobei
ich vermute dass man aber nur zur NP-Vollständigkeit kommt wenn man
unendlich viele Primzahlen zuläßt, aber die brauchen wir ja nicht…

„Optimierung“ (= Komplexität reduzieren) gar nichts mehr zu
tun.
Zweitens brauchst du für 100 Seiten 100 paarweise verschiedene
Primzahlen, deren Produkt sich dann nicht mehr in einem
normalen Integer speichern läßt. Der Ansatz stirbt also, wennn
das Produkt aller „Seiten“ 4e9 übersteigt (unsigned long), und
das ist schon nach

2 * 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 = 223092870

der Fall. Mit der Methode kannst du also nur 9 Seiten
speichern.

Warum man mit Longint arbeiten muß verstehe ich nicht. Double
Precision kann wesentlich größere Zahlen darstellen (auf meinem
Computer in der Uni wird gerade eine 64-Bit Architektur
eingerichtet…)

Ich gebe dir natürlich Recht das die Idee nicht umsetzbar ist, aber
das sollte wie gesagt nur ein Denkanstoß sein.
Das wichtigere daran: Kann ich mir einen Algorithmus ausdenken, der
einer Zahl eindeutig eine Seitenkombination zuordnet. Oder wenn
Speicher kein Problem ist. Kann ich diese Funktion anhand einer
Tabelle abspeichern. Dann hab ich am Anfang viel Mühe kann dann aber
bei viel Traffic auf die Seitenkombinationen in O(1) zugreifen.
Dieser Algorithmus hängt natürlich stark von der Anzahl der Seiten
ab!
In diesem Zusammenhang wird häufig der Begriff Hash-Tables genannt!
Damit kenn ich mich aber nicht aus…

Ciao Qasi

Hallo !

bisher habe ich das so geloest, dass ich in der usertable
(mysql) user ein feld mit komma separierten zahlen angelegt
habe…
also

USER ACCESS
A 3,4,6
B 1,2,3,4,5,6,7
C 7

Warum der Stress mit den Komma-separierten Listen ?

User Access
A 3
A 4
A 6
B 1
B 2

ist wesentlich einfacher zu verwalten…

dann hab ich auf der ersten userseite (die mit den links) alle
seiten praktisch bedingungsweise mit abfrage des arrays
inkludiert…

$res = mysql\_query("select access from tabelle where user='A' order by access");
while(list($seite)=mysql\_fetch\_row($res))
 echo "Link zu Seite $seite";

vor allem sehe ich probleme, da ich die tabellezeilen gerne
sortieren koenenn moechte… und so wie ich das jetzt
umgesetzt habe…ist das quatsch…

Wenn du nach etwas anderem als der Seitennummer sortieren willst:
für jeden Benutzer Extra: spalte sort in die Tabelle einfügen, dort die Reihenfolge eintragen und order by anpassen
für alle Benutzer gleiche Reihenfolge:
Extra Tabelle, z.b. Sort mit Seitennr, reihenfolge; im SQL dann joinen
SELECT access FROM tabelle a JOIN sort b ON a.access=b.seitennr ORDER BY b.reihenfolge

Alexander

P.S.: Wenn du die DB nicht ändern willst, obwohl das alles verienfacht:

$seiten = explode(",",$acesss); // $access ist die ,-Liste
sort($seiten); // Sortieren
foreach($seiten as $seite)
 echo "Link zu $seite";

einspruch :wink:

Warum der Stress mit den Komma-separierten Listen ?

User Access
A 3
A 4
A 6
B 1
B 2

ist wesentlich einfacher zu verwalten…

das mag sein, wenn man aber eine saubere usertabelle haben will ist sowas kontraproduktiv.
Vor allem aber müssen viele inserts bzw deletes gemacht werden, wenn sich was ändert, wo unter (komma-)separierten ein einfaches update ausreicht.

Wenn du nach etwas anderem als der Seitennummer sortieren
willst:
für jeden Benutzer Extra: spalte sort in die Tabelle einfügen,
dort die Reihenfolge eintragen und order by anpassen

urgs… also noch mehr arbeit für den admin…??
nene *g* dann lieber in der Seitendefinition mögliche sortierungskriterien angeben und jeweils nach dem passenden sortieren

P.S.: Wenn du die DB nicht ändern willst, obwohl das alles
verienfacht:

$seiten = explode(",",$acesss); // $access ist die ,-Liste
sort($seiten); // Sortieren
foreach($seiten as $seite)
echo „Link zu $seite“;

hatte er nicht schon in seinem eingangsbeitrag die Werte separiert…?
Aber so könnte man wenigstens die leerdurchläufe verhindern… jo
allerdings ist das auch nicht besonders schön gelöst wegen urlhack und so und sortieren ist da immernoch schwer…

Und wie wäre es mit dem guten alten Bitshifting ?
Rechte in einzelnen Bits verwalten, schöner gehts kaum :smile:
Rechte hinzufügen und entfernen ist auch einfach, nicht viel gerechne und Bitshifting ist sowas von schneeeeeeeeeeeeeeell.

Vielleicht finde ich gerade nen Beispiel, bevor ich mir jetzt selbst was ausdenken muss :smile:

… jaa, sogar ein php-beispiel: http://www.tutorials.de/tutorials119693.html

Viel Spass, Lars

Warum der Stress mit den Komma-separierten Listen ?

User Access
A 3
A 4
A 6
B 1
B 2

ist wesentlich einfacher zu verwalten…

das mag sein, wenn man aber eine saubere usertabelle haben
will ist sowas kontraproduktiv.
Vor allem aber müssen viele inserts bzw deletes gemacht
werden, wenn sich was ändert, wo unter (komma-)separierten ein
einfaches update ausreicht.

Ok. Kommt darauf an, was man machen will.
insert … select from geht z.B. mit der kommaliste nicht, um nach irgendwelchen Kriterien freizuschalten, ebenfalls kann man das so nicht mit anderen Tabellen joinen, zum beispiel um gleich den Ttel der Seite mit auszulesen, etc.

Ich bevorzuge so was im SQL und nicht in der Anwendung zu machen…

Wenn du nach etwas anderem als der Seitennummer sortieren
willst:
für jeden Benutzer Extra: spalte sort in die Tabelle einfügen,
dort die Reihenfolge eintragen und order by anpassen

urgs… also noch mehr arbeit für den admin…??
nene *g* dann lieber in der Seitendefinition mögliche
sortierungskriterien angeben und jeweils nach dem passenden
sortieren

Wenn man eine „Freie“ Sortierung haben will, also nicht nach bereits vorhandenen Daten, bleibt wohl nichts anderes übrig, als diese Daten erst einmal anzulegen. Egal ob nun pro Nutzer oder pro Seite. Sind die Daten, nach denen sortiert wird, in irgendweiner Weise schon vorhanden, tut es ein join und order by, was mit der kommaliste nicht so einfach geht.

P.S.: Wenn du die DB nicht ändern willst, obwohl das alles
verienfacht:

$seiten = explode(",",$acesss); // $access ist die ,-Liste
sort($seiten); // Sortieren
foreach($seiten as $seite)
echo „Link zu $seite“;

hatte er nicht schon in seinem eingangsbeitrag die Werte
separiert…?

Naja, aus dem Pseudocode bin ich nicht richtig schlau geworden.

Aber so könnte man wenigstens die leerdurchläufe verhindern…
jo
allerdings ist das auch nicht besonders schön gelöst wegen
urlhack und so und sortieren ist da immernoch schwer…

???

Alexander

das mag sein, wenn man aber eine saubere usertabelle haben
will ist sowas kontraproduktiv.

Das ist wesentlich sauberer mit der tabelle die Alexander vorgeschlagen hat :smile: Allerdings ist das dann nicht mehr die User-Tabelle sondern quasi die Berechtigungstabelle.

Vor allem aber müssen viele inserts bzw deletes gemacht
werden, wenn sich was ändert, wo unter (komma-)separierten ein
einfaches update ausreicht.

Zieht auch nicht… Wenn du z.b. einem User eine Berechtigung enziehen willst musst du ja erst den Wert selektieren, parsen, dann den User rausschmeissen, der nicht mehr reingehören soll, wieder nen String zusammenbauen und dann wieder updaten. Bei der normalisierten Form reicht sowas wie
DELETE FROM permissions WHERE userid = ‚A‘ and pageid = 1

Dazuhin weisst du bei ner kommaseparierten Liste nicht wielang der String wird, musst also potentiell nen großen Datentyp wählen. Dazuhin ist die LIKE Abfrage mit zwei Wildcards dann extrem inperformant, ok bei den Datenmengen wohl kein Problem…

Dennoch ist eine kommaseparierte Liste nicht sauber und entspricht genau nicht dem relationalen Datenmodell, da kannste das DIng dann auch gleich in ne Textdatei speichern :smile:

urgs… also noch mehr arbeit für den admin…??
nene *g* dann lieber in der Seitendefinition mögliche
sortierungskriterien angeben und jeweils nach dem passenden
sortieren

Kein Problem, man kann das Modell ja mit deinem verbinden.

SELECT * from pages, permissions
WHERE pages.id = permissions.pageid
AND permissions.userid = ‚A‘
ORDER BY (whatever…)

Grüße
Bruno

Vielen Herzlichen Dank

tach community…

danke fuer die vielen Anworten.

Ich werde sie naechstes Wochenende durcharbeiten und schauen, was ich davon umsetzen kann :smile:

Danke schoen fuer die Mühe

Grusz

PixelKoenig