Autor |
Beitrag |
Csharp-programmierer
Beiträge: 696
Erhaltene Danke: 10
Windows 8.1
C# (VS 2013)
|
Verfasst: So 30.10.16 21:34
Hallo Forum,
in der C# Applikation ist es jetzt möglich, Freundschaftsanfragen zu versenden. Wird eine Freundschaftsanfrage versendet, wird in einer Tabelle `Freundschaftsanfragen` ein Datensatz angelegt, der in etwa so aussieht. Wenn der Benutzer, an den die FA gesendet wurde, sich einloggt, kann er diese Anfrage annehmen oder ablehnen. Nimmt er diese an, dann wird der Datensatz aus der Tabelle `Freundschaftsanfragen` gelöscht. Nun wird aber ein neuer Datensatz in die Tabelle `Freundesliste` eingetragen. Diese Tabelle sieht ungefähr so aus:
ID | One | Two |
--------------------------------
1 | User1 | User2 |
--------------------------------
Soo das funktioniert schon mal. Wenn sich jetzt User 1 einloggt, muss User2 als Freund dastehen. Aber wenn User2 sich einloggt, muss User1 als Freund auftauchen.
Wie kann man diese SQL Abfrage verallgemeinern, dass die alle Freunde von dem jeweiligen eingeloggten Benutzer ausgibt?
Mit freundlichen Grüßen
_________________ "Wer keinen Sinn im Leben sieht, ist nicht nur unglücklich, sondern kaum lebensfähig" - Albert Einstein
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 30.10.16 22:08
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
Csharp-programmierer
Beiträge: 696
Erhaltene Danke: 10
Windows 8.1
C# (VS 2013)
|
Verfasst: So 30.10.16 22:31
Oder man erzeugt pro Freundschaft 2 Datensätze. Beispielsweise so:
ID | UserEingeloggt | UserAnderer |
-------------------------------------------------------
1 | Cshrp-programmierer | User2 |
-------------------------------------------------------
2 | User2 | Csharp-programmierer |
-------------------------------------------------------
Dann könnte man diese Abfrage durchführen:
SQL-Anweisung 1:
| SELECT * FROM `Freundschaften` WHERE `UserEingeloggt`=VALUE |
Aber dann würde ja mein 80 GB Webspace Speicher sicher irgendwann überlasten
_________________ "Wer keinen Sinn im Leben sieht, ist nicht nur unglücklich, sondern kaum lebensfähig" - Albert Einstein
|
|
Christian S.
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: So 30.10.16 22:50
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Csharp-programmierer
Beiträge: 696
Erhaltene Danke: 10
Windows 8.1
C# (VS 2013)
|
Verfasst: So 30.10.16 22:53
Naja...
Sagen wir mal 1000 User sind befreundet, dann sind in der Datenbank 2000 Datensätze. Ist bestimmt schon relativ viel
_________________ "Wer keinen Sinn im Leben sieht, ist nicht nur unglücklich, sondern kaum lebensfähig" - Albert Einstein
|
|
Christian S.
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: So 30.10.16 23:20
Wie kommst Du da drauf, dass das viel ist?
Du speicherst (höchstens) drei Zahlen. Eine ID für den Datensatz, eine ID für den ersten Benutuzer, eine ID für den zweiten Benutzer. Drei Zahlen mit je 32 Bit = 4 Byte. Sind also 12 Byte pro Datensatz. Sagen wir, es gibt noch einen gigantisch unrealistischen Overhead und es sind pro Datensatz 1 KB (also das 85-fache der eigentlichen Daten!). Bei 2000 Datensätzen wärst Du also bei 2 MB. Wo genau siehst Du die Grenze von 80 GB erreicht?
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 31.10.16 00:22
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
Christian S.
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mo 31.10.16 00:27
Frühlingsrolle hat folgendes geschrieben : | [...]oder du erstellst für jeden Namen eine eigene Tabelle, in der dessen Freunde aufgelistet werden. |
Was wäre der Vorteil davon?
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 31.10.16 00:29
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
Christian S.
Beiträge: 20451
Erhaltene Danke: 2264
Win 10
C# (VS 2019)
|
Verfasst: Mo 31.10.16 00:36
Du meinst, wenn ich dann bei 1000 Nutzern 1000 Tabellen habe?
Und wie frage ich dann z.B. ab, wer alles Benutzer X "gefreundet" hat?
_________________ Zwei Worte werden Dir im Leben viele Türen öffnen - "ziehen" und "drücken".
|
|
Palladin007
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Mo 31.10.16 00:45
In der heutigen Zeit ist der Datenspeicher die billigste Resource, um die würde ich mir als letztes Gedanken machen ^^
Klar, solltest Du einige Grundregeln beachten, aber solange Du nicht zig Daten an zig verschiedenen Stellen redundant hältst, sollten deine 80GB eigentlich locker und mit links ausreichen.
Kommt natürlich drauf an, was Du noch so für Daten sammelst
Und was die Freundschaften angeht:
Variante 1:
Wie Du schon gesagt hast:
Für jede neue Freundschaft bekommt jeder User einen Freundschaft-Eintrag.
Das hätte den Vorteil, dass pro Person eigene Daten pro Freundschaft gespeichert werden können.
Einen Vorteil in der Abfrage sehe ich nicht.
Variante 2:
Jede Freundschaft zwischen zwei Personen ist "eindeutig"
Pro Freundschaft gibts dann genau einen Datensatz.
Gemeinsame Daten pro Freundschaft sind dann leichter zu verwalten, eine Person kann aber keine eigenen Daten für eine Freundschaft haben.
In SQL ungefähr so:
SQL-Anweisung 1: 2: 3:
| SELECT * FROM Freundschaften WHERE User1Id = @userId OR User2Id = @userId |
Die wichtigste Frage bleibt also:
Was genau willst Du machen?
Braucht eine Freundschaft pro Person eigene Daten?
Oder soll jede Freundschaft eigene Daten gemeinsam für beide Beteiligten haben?
Je nachdem, was Du brauchst, musst Du die Variante wählen.
Die Komplexität der SQL-Abfrage, der Umfang der Daten oder Performance sind bei einem so kleinen Rahmen eher drittrangig.
Aber mach bitte nicht so Spielereien wie pro Freund eine neue Spalte oder pro Person eine neue Freundes-Tabelle.
Potentielle Probleme dabei:
- ORMs kann man sich damit eigentlich sparen, es gibt ja keine statische Klassenstruktur mehr, in die gängige ORMs das mappen können. Oder ich weiß von kenem ORM, was das im laufenden Betrieb kann.
- Die SQL-Abfragen lassen sich nicht mehr über einfache Parameter zusammenbauen, einfache WHERE-Klauseln reichen nicht mehr, andere Dinge wie Group By dürften schwierig werden, etc.
- Eine Freundschafts-Anfrage braucht auf einmal DDL-Rechte auf dem Server, was ich für fragwürdig halte
- Mittelfristig dürfte das auch ein Performance-Problem darstellen, wenn Du nicht nur tausende Daten (was echt wenig ist), sondern tausende Tabellen hast. Und tausende Tabellen, das IST viel
Hab ich was vergessen?
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 31.10.16 01:11
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
Th69
Beiträge: 4785
Erhaltene Danke: 1055
Win10
C#, C++ (VS 2017/19/22)
|
Verfasst: Mo 31.10.16 10:27
Also das mit den eigene Tabellen paßt nun wirklich nicht zu einer normalisierten Datenbank.
Ich würde die Abfrage ähnlich wie Palladin007 machen, nur daraus zwei machen und diese beiden vereinen:
SQL-Anweisung 1: 2: 3: 4: 5: 6: 7: 8: 9:
| SELECT User2Id FROM Freundschaften WHERE User1Id = @userId
UNION
SELECT User1Id FROM Freundschaften WHERE User2Id = @userId |
|
|
Palladin007
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Mo 31.10.16 11:10
Zitat: | 1000 Benutzer / 1000 Tabellen, oder 1 Tabelle und ein vielfaches an Datensatzen, also mehr als 1000! |
Wenn 1000 Benutzer 1000 Freunde haben, dann brauchst Du 1000 Tabellen mit 1000 Datensätzen.
1000 Tabellen tun weh in der Performance
Alles in einer Tabelle würde bedeuten, dass für jede Person und für jede Freundschaft zwei Datensätze angelegt werden.
Sprich: 1000 * 1000 * 2 = 2000000 Datensätze
Das wäre in der Tat viel, allerdings hast Du die Datenmenge bei 1000 Tabellen auch plus die Daten, die der Server braucht um die Tabellen zu verwalten.
Und bei 1000 Tabellen kann der Server nicht über alle Daten indizieren.
Und DAS, der letzte Punkt, der sollte eigentlich ein KO-Kriterium sein
Wenn Du 2 Millionen Datensätze in einer Tabelle hast, kann der Server auf alle Datensätze indizieren, was einen deutlichen Performance-Vorteil bedeuten kann.
Wenn Du diese 2 Millionen Datensätze auf 1000 Tabellen auf teilst, dann indiziert der Server über 1000 Datensätze pro Tabelle, was witzlos wäre.
|
|
Csharp-programmierer
Beiträge: 696
Erhaltene Danke: 10
Windows 8.1
C# (VS 2013)
|
Verfasst: Mo 31.10.16 12:55
Jetzt habe ich gestern Abend noch bin tief in die Nacht an dem PHP Script rumgewerkelt, dass die Usernames in IDs verwandelt werden. Jetzt haut alles so hin, dass die C# Anwendung die Usernames zur PHP Datei schickt und diese demnach die zugehörige ID raussucht und in die Datenbank schreibt. Im Moment läuft es noch so, dass der doppelte Datensatz eingetragen wird.
Was soll noch passieren?
Die eine Datenbank soll lediglich alle Freundschaften speichern. Heute versuche ich noch einen PHP Script zu basteln, der dann die ganzen Freunde, samt anderen Daten ausgibt...
Im Moment habe ich ja noch den doppelten Datensatz für eine Freundschaft.
SQL-Anweisung 1: 2: 3: 4: 5: 6: 7: 8: 9:
| SELECT User2Id FROM Freundschaften WHERE User1Id = @userId
UNION
SELECT User1Id FROM Freundschaften WHERE User2Id = @userId |
Und mit diesem SQL Befehl bekommt man dann alle Freundschaften anhand eines Datensatzes?
_________________ "Wer keinen Sinn im Leben sieht, ist nicht nur unglücklich, sondern kaum lebensfähig" - Albert Einstein
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 31.10.16 14:44
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
jfheins
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Mo 31.10.16 15:04
Was meinst du damit? Die Abfrage?
Das liegt halt daran, dass die Freundschaft kommutativ ist. Man kann auch ein System implementieren, bei dem man Leute einseitig de-frienden kann. Dann hätte die Reihenfolge wieder eine Bedeutung.
Aber so ist es egal, und bevor du einfach die doppelte Menge an Daten in die DB kippst, ist es doch einfach eine Abfrage wie "... WHERE User1Id = @userId OR User2Id = @userId" abzusetzen.
Für diesen Beitrag haben gedankt: FinnO
|
|
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 31.10.16 19:06
- Nachträglich durch die Entwickler-Ecke gelöscht -
|
|
Csharp-programmierer
Beiträge: 696
Erhaltene Danke: 10
Windows 8.1
C# (VS 2013)
|
Verfasst: Mo 31.10.16 21:08
Ich habe es jetzt so gemacht, dass pro Freundschaft nur ein Datensatz angelegt wird. Ich habe folgenden Code zusammengestellt:
PHP-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| $CurrentUser = mysqli_real_escape_string($conn, $_POST["currUsr"]); $sqlQuery = "SELECT `To_ID` FROM `MainlysoftFreundesliste` WHERE `To_ID`='$CurrentUser' OR `From_ID`='$CurrentUser'"; $result = mysqli_query($conn, $sqlQuery); if($result) { $newQuery = "SELECT `name`, `vorname`, `language`, `gender` FROM `MainlysoftBenutzer` WHERE `ID`='$CurrentUser'"; if ($result->num_rows > 0) { while($row = $result->fetch_assoc()) { echo $row["name"]. ";" . $row["vorname"]. ";" .$row["language"]. ";" .$row["gender"]. ""; } } else { echo "0 results"; } } else { echo "Error in SQL statement"; } |
Jetzt wird mir ja nur "To_ID" rausgesucht. Aber wenn ich jetzt auch "Von_ID" raussuchen lass, weiß ich ja nicht, welcher von den beiden Usern sich eingeloggt hat. Verseht ihr den logischen Fehler?
_________________ "Wer keinen Sinn im Leben sieht, ist nicht nur unglücklich, sondern kaum lebensfähig" - Albert Einstein
|
|
Ralf Jansen
Beiträge: 4705
Erhaltene Danke: 991
VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
|
Verfasst: Mo 31.10.16 21:21
Zitat: | Jetzt wird mir ja nur "To_ID" rausgesucht. Aber wenn ich jetzt auch "Von_ID" raussuchen lass, weiß ich ja nicht, welcher von den beiden Usern sich eingeloggt hat. Verseht ihr den logischen Fehler? |
Nein. Warum solltest du, weil das SQL änderst, ~vergessen~ wer in $CurrentUser steht?
|
|