2010-02-10 15 views
5

Supponiamo di avere un sito popolare. Dobbiamo implementare la messaggistica simile alla posta tra gli utenti. soluzione tipica è quella di utilizzare 2 tabelle:Database MySQL scalabile per messaggistica simile alla posta

Utenti (user_id)

Messaggi (message_id, sender_id (riferimenti ID_utente), receiver_id (riferimenti user_id), soggetto, corpo).

Questo metodo ha 2 limitazioni significative

  1. Tutti i messaggi di tutti gli utenti sono memorizzati in una tabella che conduce ad esso di alto carico e diminuendo le prestazioni complessive del database.
  2. Quando qualcuno deve inviare un messaggio a più utenti contemporaneamente, il messaggio viene copiato (recipients_count) volte.

L'altra soluzione utilizza 3 tabelle:

Utenti (user_id)

Sent_messages (sent_id, sender_id (riferimenti user_id), soggetto, corpo)

Received_messages (send_id, receiver_id (riferimenti user_id), oggetto, corpo)

l'oggetto e il corpo dei messaggi ricevuti vengono copiati dai campi corrispondenti di messaggi inviati.

Questo metodo porta a

  1. denormalizing database copiando le informazioni da un tavolo all'altro
  2. Gli utenti possono in realtà delete messaggi inviati/ricevuti senza rimuoverli dai ricevitori/trasmettitori.
  3. I messaggi richiedono circa 2 volte di spazio in più
  4. Ogni tabella viene caricata circa 2 volte di meno.

Così qui vanno le domande:

  1. Chi di progettazione considerato è meglio per alto carico e scalabilità? (Penso che sia il secondo)
  2. Esiste un altro design di database in grado di gestire un carico elevato? Che cos'è? Quali sono i limiti?

Grazie!

P.S. Capisco che prima di arrivare a questi problemi di scalabilità il sito deve avere molto successo, ma voglio sapere cosa fare se necessario.

UPDATE

Attualmente per le prime versioni sarò con il design proposto da Daniel Vassallo.Ma se tutto andrà bene in futuro, il design sarà cambiato con il secondo. Grazie a Evert per aver dissipato la mia apprensione al riguardo.

risposta

3

È possibile evitare di copiare il corpo del messaggio più volte nel caso in cui un messaggio venga inviato a più destinatari. Qui è un'altra opzione che si può prendere in considerazione:

  • utenti (user_id)

  • messaggi (message_id, sender_id, soggetto, corpo)

  • received_messages (message_id, user_id, address_mode, cancellato)

Questo modello potrebbe essere più simile a Twitter che simile a un messaggio di posta elettronica, ma potrebbe presentare alcuni vantaggi.

Le regole sono che:

  • Un messaggio può essere inviato solo da un utente, si fa riferimento nel sender_id di ogni messaggio.
  • Ogni destinatario verrà definito nella tabella received_messages. Il campo address_mode può definire se un messaggio è stato inviato direttamente al destinatario, o come CC, o forse come BCC. Questo campo è ovviamente facoltativo.
  • I messaggi eliminati dai destinatari contrassegneranno il flag eliminato nella tabella received_messages.
  • I messaggi inoltrati e inviati ai messaggi devono essere ricreati con un nuovo sender_id. Il corpo del messaggio può essere quindi modificato.

Questi sono alcuni dei vantaggi:

  • Questo richiede meno spazio rispetto alle due opzioni menzionate nella domanda iniziale, soprattutto se gli utenti in genere inviare messaggi a più destinatari.
  • Caching più semplice della tabella dei messaggi, poiché i messaggi non vengono mai duplicati.
  • Il destinatario che elimina un messaggio non cancella le informazioni che il messaggio è stato inviato a questo utente. Sarà semplicemente contrassegnato come 'cancellato' nella tabella received_messages.
  • E si ottiene anche un modello normalizzato.

Per la maggior parte delle applicazioni, se si utilizza un livello di isolamento ottimistica con il modello di cui sopra, si dovrebbe non avere problemi di prestazioni, anche se vi aspettate messaggi da scambiare al ritmo di un paio al secondo. Se invece ti stai aspettando centinaia o migliaia di messaggi al secondo, allora potrebbe davvero essere il caso di prendere in considerazione altre opzioni.

+0

Grazie!Ho preso in considerazione anche questo disegno. In realtà, dopo aver postato questa domanda I (mentalmente :)) ha modificato il primo progetto in Users (id_utente) Messaggi (message_id, sender_id, receiver_id, message_content_id) Message_content (message_content_id, subject, body) Quindi entrambi questi disegni sono migliori del primo (nello spazio occupato e nelle prestazioni del tavolo). Forse la domanda deve essere qualcosa di simile: è meglio memorizzare tutti i messaggi in una tabella o copiarli in due? Quanto sarà significativo l'impatto sulla performance? –

1

In generale, le dimensioni del database non saranno un problema. La velocità è molto più importante.

Pertanto, sarei tentato di optare per l'opzione due. Proprio come hai detto tu, rende le cose come cancellare i messaggi molto più facilmente, e sono abbastanza sicuro che questo è un modo molto comune per farlo.

Problemi correlati