简体   繁体   中英

Database design: Multiple tables per user

I'm attempting to build a database that stores messages for multiple users. Each user will be able to send/receive 5 different message "types" (strictly a label, actual data types will be the same). My initial thought was to create multiple tables for each user, representing the 5 different message types. I quickly learned this is not such a good idea. My next thought was to create 1 table per message type with a users column, but I'm not sure that's the best method either from a performance perspective. What happens if user 1 sends 100 message type 1's, while user 3 only sends 10? The remaining fields would be null values, and I'm really not sure if that makes a difference or not. Thoughts? Suggestions and/or suggested reading? Thank you in advance!

No, that (the idea given in the subject of this question) will be tremendously inefficient. You'll need to introduce a new table each time a new user is created, and querying all them at once would be a nightmare.

It's far easier to be done with a single table for storing information about message. Each row in this table will correspond to one - and only - message.

Besides, this table should probably have three 'referential' columns: two for linking a specific message to its sender and receiver, and one for storing its type, that can be assigned only a limited set of values.

For example:

MSG_ID | SENDER_ID | RECEIVER_ID | MSG_TYPE | MSG_TEXT 
------------------------------------------------------
   1   |     1     |     2       |    1     | .......
   2   |     2     |     1       |    1     | #######
   3   |     1     |     3       |    2     | $$$$$$$
   4   |     3     |     1       |    2     | %%%%%%%

...   

It'll be quite easy to get both all the messages sent by someone (with WHERE sender_id = %someone_id% clause), sent to someone ( WHERE receiver_id = %someone_id% ), of some specific type ( WHERE msg_type = %some_type% ). But what's best of it, one can easily combine these clauses to set up more sophisticated filters.


What you initially thought of, it seems, looks like this:

IS_MSG_TYPE1 | IS_MSG_TYPE2 | IS_MSG_TYPE3 | IS_MSG_TYPE4
---------------------------------------------------------
     1       |      0       |      0       |      0   
     0       |      1       |      0       |      0
     0       |      0       |      1       |      0

It can be NULL s instead of 0 , the core is still the same. And it's broken. Yes, you can still get all the messages of a single type with WHERE is_msg_type_1 = 1 clause. But even such an easy task as getting a type of specific message becomes, well, not so easy: you'll have to check each of these 5 columns until you find the one that has truthy value.

The similar difficulties expect the one who tries to count the number of messages of each types (which is almost trivial with the structure given above: COUNT(msg_id)... GROUP BY msg_type .

So please, don't do this. ) Unless you have a very strong reason not to, try to structure your tables so that with the time passing by they will grow in height - not in width.

The remaining fields would be null values

Except if you're designing your database vertically, there will be no remaining fields.

user   int
msgid  int
msg    text
create table `tv_ge_main`.`Users`( 
   `USER_ID` bigint NOT NULL AUTO_INCREMENT , 
   `USER_NAME` varchar(128), 
   PRIMARY KEY (`ID`)
 )

create table `tv_ge_main`.`Message_Types`( 
   `MESSAGE_TYPE_ID` bigint NOT NULL AUTO_INCREMENT , 
   `MESSAGE_TYPE` varchar(128), 
   PRIMARY KEY (`ID`)
 )

create table `tv_ge_main`.`Messages`( 
   `MESSAGE_ID` bigint NOT NULL AUTO_INCREMENT , 
   `USER_ID` bigint , 
   `MESSAGE_TYPE_ID` bigint , 
   `MESSAGE_TEXT` varchar(255) , 
   PRIMARY KEY (`ID`)
 )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM