Andy : Interne Mitteilung an mehrere Benutzer in einem Portal

Guten Abend.

Ich betreue ein kleines Internetportal, welches nur ein paar tausend Benutzer zählt. Dort haben die Benutzer die Möglichkeit sich gegenseitig Nachrichten zukommen zu lassen, welche dann eben dort in einer Art Postfach abgerufen und angesehen werden können. Ferner produziert ergeben sich auch allerhand automatische Mitteilungen, welche ebenso dann eben Benutzer-gebunden in dessen jeweiliges Postfach abgelegt werden. Nun ist es aber so, dass dies eine recht hohe Zahl automatisch generierter Mitteilungen ist, und der Kreis der Benutzer auch stark variiert, welche eben dann eine dieser automatischen Mitteilungen bekommen. So kann das dann nur einer, sowohl als auch alle Betreffen, oder nur einen bestimmten Teil. In Zahlen also einer bis ein paar tausend.
Technisch sieht das so aus, dass dahinter eine Datenbanktabelle steht, in der bisher jede Mitteilung für einen jeweilige Benutzer gespeichert wird (mit Benutzer-ID des jeweiligen Empfängers und eben der Text). Nun stört mich es aber, dass, wenn eine Nachricht an bspw. 5000 Benutzer verteilt werden soll, ich eigentlich nicht Willens bin dann auch für jeden Benutzer einen Zeile an die Datenbank zu schicken um eben dann in dem Fall 5000 Zeilen da einzutragen. Ich nehme an, dass das ja schon mitunter dann sehr zu Lasten der Performance gehen könnte, auch erscheint mir das sehr umständlich. Und die Laufzeit der ganzen Aktion beeinträchtigt ja dann mitunter auch stark die Geschwindigkeit der Seite in der Ausfürhung an sich.
Was ich also eigentlich suche ist eine Technik, oder vielmehr einen Denkansatz, wie ich eben dort mit wenig Aufwand, Zeitverlust und "Performance-günstig" viele Zeilen auf einmal in die Datenbank eintragen kann. Da in meinem Fall sich nur der "Empfänger" der Nachricht unterscheidet, vielleicht sowas wie ein BCC-Feld (in einer E-Mail), wo ich dann eben alle Empfänger eintrage, während der Text nur einmal da steht. Gut, aber das währe dann womöglich auch ein recht langer Query-String an die Datenbank.
Ach, ich habe derzeit keinen vernünftigen Ansatz irgendwie - jemand eine Idee? Für jeglichen groben Denkansatz wäre ich sehr dankbar.

Sollten genauere (technische) Fragen bezüglich der Umgebung bestehen, die ich dort zur Verfügung habe, so werde ich das gern beantworten.

Ach, was vielleicht noch erwähnt werden sollte, da ich schon E-Mail erwähnte weiter oben; eben das, dies einfach über E-Mail (Mailinglist o.ä.) zu realisieren, ist in dem Fall quasi ausgeschlossen. Allein schon, weil aufgrund der mitunter eben hohen Zahl Mitteilungen, dies von der Mehrzahl der Benutzer eher als störend empfunden würde - so eine kleine Umfrage im Voraus kürzlich dort. Die Umsetzung über die "interne Mitteilungspost" wurde hingegen befürwortet.

Das war es erstmal soweit..

  1. Grüße,
    sind Untergruppen bekannt?
    du könntest es andersherum lösen - indem jeder Nutzer seiner "Art" entsprechend eine Nachricht "anfordert", die angezeigt wird falls es dazu was gibt?
    MFG
    bleicher

    --
    __________________________-

    FirefoxMyth
    1. Grüße,

      Grüße zurück :-)

      sind Untergruppen bekannt?

      Das wäre zwar denkbar, aber nicht praktikabel, da ja bei jeder neuen Nachricht sich der Empfängerkreis völlig anders als ein anderer vorher zusammensetzen kann.

      du könntest es andersherum lösen - indem jeder Nutzer seiner "Art" entsprechend eine Nachricht "anfordert", die angezeigt wird falls es dazu was gibt?

      Das ist ein interessanter Ansatz. Danke.

      MFG

      ebenso

      bleicher

      Andy

      1. Grüße,

        Das wäre zwar denkbar, aber nicht praktikabel, da ja bei jeder neuen Nachricht sich der Empfängerkreis völlig anders als ein anderer vorher zusammensetzen kann.

        na ja .- aber nicht völlig willkürlich?
        was ist der zweck der nachricht denn, wenns kein geheimnis ist?
        MFG
        bleicher

        --
        __________________________-

        FirefoxMyth
  2. Hallo, mach das Feld für die Empfänger-ID nulllable. Und für den Empfänger änderst du die Query (welche die für ihn bestimmten Nachrichten anzeigen soll) einfach darauf ab:

    ...
    WHERE (Empfaenger_ID IS NULL) OR (Empfaenger_ID = @variable@)

    @variable@ ist dabei die Id des Users der grad seine Nachrichten sehen will.

    Ciao, Frank

    1. Hallo,

      Hallo

      mach das Feld für die Empfänger-ID nulllable. Und für den Empfänger änderst du die Query (welche die für ihn bestimmten Nachrichten anzeigen soll) einfach darauf ab:

      ...
      WHERE (Empfaenger_ID IS NULL) OR (Empfaenger_ID = @variable@)

      NULL würde nicht funktionieren, denn wenn nun andere Nachrichten dazu kommen, die eben für einen anderen Benutzerkreis bestimmt sind als jenen einer älteren Nachricht, dann habe ich mehrere Mitteilungen, welche aber alle als Empfänger-Kennung NULL haben, aber an eben verschiedene Benutzer gerichtet sind, so würden alle Benutzer alle Mitteilungen ja lesen können. Zudem kann der Benutzer dann eine solche Mitteilung mit NULL-Empfänger nicht einfach löschen (in seinem Postfach), da diese Mitteilung ja dann für alle anderen, für die die Mitteilung auch bestimmt wäre, garnicht mehr existieren würde. Im schlimmsten Fall ist also so dann eine Nachricht an 8912 Leute gerichtet, der erste liest es und klickt "löschen" und weg ist es. Alle anderen 8911 bekommen das nie zu Gesicht. Und wie schon gesagt, es sind ja durchaus mehrere Mitteilungen an unterschiedliche Gruppen von Benutzern.

      Es muss also tatsächlich für jeden mit der Nachricht angesprochenen auch eine eigenen existieren, damit der die eben dann nach dem lesen auch löschen kann. Ich suche quasi nur einen Weg viele Datensätze möglichst ohne viel unsinniges und doppeltes Drumherum in die Tabelle zu bekommen.

      Ich könnte mir auch (nun) vorstellen, dass das Empfänger-Feld mehrere Benutzerkennungen beinhalten würde, und je nachdem, wer das dann bereits gelesen und/oder gelöscht (in seinem Postfach jedenfalls) hat, dessen BEnutzerkennung aus dem Empfängerfeld entfernt wird. Aber bei der von mir eingesetztem MySQL-Datenbank würde mir nun kein vernünftiger Datentyp für sowas einfallen - oder gibt es da doch etwas?
      Ich kann ja nun schließlich nicht ein SET-Feld anlegen, mit den Werten 1 bis MAXINT (der Wertebreich meiner Benutzerkennungen) und dann per Default eben die angesprochenen Benutzerkennungs-Werte setzen und (nach dem lesen/entfernen) dieses wieder aufheben. Das wird schon wegen der "Spannweite" des SET-Typs nicht gehen. Aber genau sowas würde ich wohl benötigen.
      Wäre es denn sinnvoll ein Extrafeld einzurichten indem alle BEnutzerkennungen (der Empfänger) enthalten sind (meinetwegen vom Typ TEXT, mitunter also bei 8000 Empfängern als ellenlangen String) und die dann ggf. einfach da heraus zu löschen? Ist das nicht dann nebst der Datenbank ebenfalls für das ausführende Skript eine Zumutung bei solchen Operationen?

      Fragen über Fragen :(

      Ciao, Frank

      1. Hi,

        SET Felder sind immer eine Lösung für nicht real vorhandene Probleme bzw. selbstgemachte Probleme.

        Okay, dann bringst du eben noch ein Feld namens Empfänger-Gruppe mit ins Spiel welches NULL sein kann. Kann doch nun nicht so schwierig sein, das Konzept "NULL bedeutet ALLE" weiterzudenken.

        Ciao, FF

      2. Hallo,

        Zudem kann der Benutzer dann eine solche Mitteilung mit NULL-Empfänger nicht einfach löschen (in seinem Postfach), da diese Mitteilung ja dann für alle anderen, für die die Mitteilung auch bestimmt wäre, garnicht mehr existieren würde. Im schlimmsten Fall ist also so dann eine Nachricht an 8912 Leute gerichtet, der erste liest es und klickt "löschen" und weg ist es. Alle anderen 8911 bekommen das nie zu Gesicht. Und wie schon gesagt, es sind ja durchaus mehrere Mitteilungen an unterschiedliche Gruppen von Benutzern.

        Hmm, dazu sind relationale Datenbanken doch da: Man legt versch. Tabellen an und verknüpft diese untereinander so, dass in einer einzelnen Tabelle keine Redundanz besteht.

        Man erstellt z.B. mittels einer Tabelle eine many-to-many-Verknüfung (inner/outer join oder wie das in SQL heißt), welche rechts die Nachrichten-Tabelle mit eindeutiger Nachrichten-ID und links die Empfänger-Tabelle mit eindeutiger Benutzer-ID verknüft. Löscht einer eine Nachricht in seinem Postfach, dann wird nur die Verknüfung in der mittleren Tabelle entfernt, nicht die Nachricht selber und natürlich auch nicht der Benutzer.

        Irgendwie so, mal als grober Denkanstoß.

        Gruß, Don P

  3. Ich nehme an, dass das ja schon mitunter dann sehr zu Lasten der Performance gehen könnte

    Glaub ich weniger, je nachdem wie oft solche Nachrichten gibt.

    Hast du auch benutzerabhängige Flags für "gelesen" und so? Dann kommst du nicht drum rum, jeder einzelnen Nachricht einen eigenen Eintrag zu geben.
    Aber du könntest das in einer zweiten Tabelle halten, die dann nur auf einen einzigen ausgeschriebenen Eintrag referenziert. Damit hättest du den Text nur einmal statt 5000 mal und halt weiterhin pro Nachricht einen Eintrag (ohne den Text) in einer Nachrichtentabelle.

    1. Ich nehme an, dass das ja schon mitunter dann sehr zu Lasten der Performance gehen könnte
      Glaub ich weniger, je nachdem wie oft solche Nachrichten gibt.

      Das kann schon sehr viel werden. 1000 ca. derzeit am Tag. Jede mit einer variablen Anzahl von Empfängern und somit halt dann jeweils auch Einträgen in der DB-Tabelle.

      Hast du auch benutzerabhängige Flags für "gelesen" und so?

      Ja, habe ich.

      Dann kommst du nicht drum rum, jeder einzelnen Nachricht einen eigenen Eintrag zu geben.

      Schade, aber ich freunde mich damit an. Nur, muss ich für jede Zeile auch eine einzelne QUERY an die Datenbank senden? Kann man das nicht irgendwie optimieren? Also in etwa ein Query wie "INSERT ... daten, andereDaten, text, (Benutzer1, Benutzer5, Benutzer300, Benutzer...) INTO.. " usw. für aber tausend (bis eben auf die BenutzerIDs des Empfängers) gleiche Zeilen?
      (Das Beispiel sollte nun nur veranschaulichend wirken und ist natürlich von der Syntax her Blödsinn. Ich wollte nur meinen Gedanken verdeutlichen.)

      Aber du könntest das in einer zweiten Tabelle halten, die dann nur auf einen einzigen ausgeschriebenen Eintrag referenziert. Damit hättest du den Text nur einmal statt 5000 mal und halt weiterhin pro Nachricht einen Eintrag (ohne den Text) in einer Nachrichtentabelle.

      Das spart mir zwar dann nicht die einzelnen Einträge, aber zumindest einigen Speicherplatz auf Dauer. Das hatte ich bisher noch garnicht berücksichtigt - danke!

      1. Das kann schon sehr viel werden. 1000 ca. derzeit am Tag.

        1000 Nachrichten, die jeweils an bis zu 5000 Empfänger gehen? Dann bau gleich noch ne Funktion ein, die den Usern einen Urlaubsantrag ausdruckt, damit die das auch lesen können :-)
        Also ich denk mal 1000 Nachrichten an jeweils wenige Empfänger.

        Schade, aber ich freunde mich damit an. Nur, muss ich für jede Zeile auch eine einzelne QUERY an die Datenbank senden?

        Du kannst sowas hier machen
        INSERT INTO ...
        SELECT feld1, 'fester String', ...
        FROM Tabelle

        Damit baust du ein SELECT, das dir z.B. die gewünschten UserIDs aus einer Tabelle holt (sofern die da passend drin stehen) und trotzdem noch ein fester Stringwert (deine nachricht) dabei steht. Das Ergebnis davon wird dann wieder in eine andere Tabelle eingefügt.

        Falls du wirklich einzelne Statements brauchst weil du die UserIDs einzeln angeben musst, kannst du das genauso nutzen, in dem du deine Nachricht in eine Tabelle schreibst (da reicht ja ne temporäre) und die dann auf diese Weise dazu selectierst.