Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Database best practices

I have a table which stores comments, the comment can either come from another user, or another profile which are separate entities in this app.

My original thinking was that the table would have both user_id and profile_id fields, so if a user submits a comment, it gives the user_id leaves the profile_id blank

is this right, wrong, is there a better way?

like image 470
Tim Avatar asked May 27 '10 06:05

Tim


3 Answers

Whatever is the best solution depends IMHO on more than just the table, but also how this is used elsewhere in the application.

Assuming that the comments are all associated with some other object, lets say you extract all the comments from that object. In your proposed design, extracting all the comments require selecting from just one table, which is efficient. But that is extracting the comments without extracting the information about the poster of each comment. Maybe you don't want to show it, or maybe they are already cached in memory.

But what if you had to retrieve information about the poster while retrieving the comments? Then you have to join with two different tables, and now the resulting record set is getting polluted with a lot of NULL values (for a profile comment, all the user fields will be NULL). The code that has to parse this result set also could get more complex.

Personally, I would probably start with the fully normalized version, and then denormalize when I start seeing performance problems

There is also a completely different possible solution to the problem, but this depends on whether or not it makes sense in the domain. What if there are other places in the application where a user and a poster can be used interchangeably? What if a User is just a special kind of a Profile? Then I think that the solution should be solved generally in the user/profile tables. For example (some abbreviated pseudo-sql):

create table AbstractProfile (ID primary key, type ) -- type can be 'user' or 'profile'
create table User(ProfileID primary key references AbstractProfile , ...)
create table Profile(ProfileID primary key references AbstractProfile , ...)

Then any place in your application, where a user or a profile can be used interchangeably, you can reference the LoginID.

like image 83
Pete Avatar answered Oct 13 '22 01:10

Pete


If the comments are general for several objects you could create a table for each object:

user_comments (user_id, comment_id)
profile_comments (profile_id, comment_id)

Then you do not have to have any empty columns in your comments table. It will also make it easy to add new comment-source-objects in the future without touching the comments table.

like image 28
becquerel Avatar answered Oct 13 '22 00:10

becquerel


Another way to solve is to always denormalize (copy) the name of the commenter on the comment and also store a reference back to the commenter via a type and an id field. That way you have a unified comments table where on you can search, sort and trim quickly. The drawback is that there isn't any real FK relationship between a comment and it's owner.

like image 25
cherouvim Avatar answered Oct 13 '22 00:10

cherouvim