Database design question

TechBoyJK

Lifer
Oct 17, 2002
16,699
60
91
I'm designing a messaging application for a website.

I'm at a cross roads as to how to design the main message table, which will include id's for both the sender and receiver.

The main user table includes both a unique ID (aka '12345') and a username (aka 'johndoe123'). Attempting normalization, I'm undecided whether to base the messages on the ID, Username, or both.

With the current structure, the ID is the primary key of the user table, and the username is a unique, permananent varchar value. After the creation of a user, both the username and ID will not change.

If I use the user ID in the message table, anytime a record is called/searched/selected a subquery or join will need to be ran to fetch the related username of the user ID. So if I want to select all 'inbox' records for a user, those inbox message records will only have the unique ID's of those members that sent that user a message. If there are 1,000 messages, all from different users, the join or additional queries will need to fetch each username for each of the 1,000 user Id's of each sender. 1,000 queries. That's alot of extra load.

I'm thinking it would probably be best to include both the unique ID AND the unique username to prevent having to use more than just a single query to fetch message records. I know this isn't perfect normalization, but I think I'd rather err on the side of performance vs. a fully normalized table structure.

Seem logical?
 

BoberFett

Lifer
Oct 9, 1999
37,562
9
81
Originally posted by: TechBoyJK
After the creation of a user, both the username and ID will not change.

Don't count on that.

Also, what you're talking about is very simple joins. If an extra join to get username based on a primary key is putting to much of a strain on your database, you're doing something wrong.

select sender, message
from messages
join users recipient on messages.userid = recipient.userid
join users sender on messages.senderid = sender.userid
where recipient.username= 'TechBoyJK'

There's no need for a subquery, you're right that IS inefficient. Use table aliasing to your advantage.
 

KIAman

Diamond Member
Mar 7, 2001
3,342
23
81
What RDBMS are you using? Normalize and let the software manage the best execution path. Have you actually ran a simulation on the overhead and determined the cost?
 

TechBoyJK

Lifer
Oct 17, 2002
16,699
60
91
Originally posted by: BoberFett
Originally posted by: TechBoyJK
After the creation of a user, both the username and ID will not change.

Don't count on that.

Also, what you're talking about is very simple joins. If an extra join to get username based on a primary key is putting to much of a strain on your database, you're doing something wrong.

select sender, message
from messages
join users recipient on messages.userid = recipient.userid
join users sender on messages.senderid = sender.userid
where recipient.username= 'TechBoyJK'

There's no need for a subquery, you're right that IS inefficient. Use table aliasing to your advantage.

ID is the unique id for the recordset (primarykey) and as a business rule, the username will not change. So I can count on that. I know I would just join the two tables (usertable/messagetable) on the uniqueID, pull the message from the message table and the pull the username from the usertable.. But it seems performance would be greatly better, especially on larger recordsets to just use a single table...

 

TechBoyJK

Lifer
Oct 17, 2002
16,699
60
91
Originally posted by: KIAman
What RDBMS are you using? Normalize and let the software manage the best execution path. Have you actually ran a simulation on the overhead and determined the cost?

MS-SQL

When I was studing for the SQL Server database design exam, there were specific questions about when it was not a good idea to normalize when performance gains would merit the troubles of duplicate data.
 

nakedfrog

No Lifer
Apr 3, 2001
59,243
13,845
136
Originally posted by: TechBoyJK
Originally posted by: BoberFett
Originally posted by: TechBoyJK
After the creation of a user, both the username and ID will not change.

Don't count on that.

Also, what you're talking about is very simple joins. If an extra join to get username based on a primary key is putting to much of a strain on your database, you're doing something wrong.

select sender, message
from messages
join users recipient on messages.userid = recipient.userid
join users sender on messages.senderid = sender.userid
where recipient.username= 'TechBoyJK'

There's no need for a subquery, you're right that IS inefficient. Use table aliasing to your advantage.

ID is the unique id for the recordset (primarykey) and as a business rule, the username will not change. So I can count on that. I know I would just join the two tables (usertable/messagetable) on the uniqueID, pull the message from the message table and the pull the username from the usertable.. But it seems performance would be greatly better, especially on larger recordsets to just use a single table...

I doubt you'd see a significant difference in the scenario you put forth.
 

BoberFett

Lifer
Oct 9, 1999
37,562
9
81
Whatever you say. You already sound like you've made up your mind, so why ask here? Denormalize, but don't come back crying later when you discover that your "business rules that never change" have changed, and you have to now write triggers that update other tables because you didn't normalize.
 

KLin

Lifer
Feb 29, 2000
29,556
163
106
Originally posted by: nakedfrog
Originally posted by: TechBoyJK
Originally posted by: BoberFett
Originally posted by: TechBoyJK
After the creation of a user, both the username and ID will not change.

Don't count on that.

Also, what you're talking about is very simple joins. If an extra join to get username based on a primary key is putting to much of a strain on your database, you're doing something wrong.

select sender, message
from messages
join users recipient on messages.userid = recipient.userid
join users sender on messages.senderid = sender.userid
where recipient.username= 'TechBoyJK'

There's no need for a subquery, you're right that IS inefficient. Use table aliasing to your advantage.

ID is the unique id for the recordset (primarykey) and as a business rule, the username will not change. So I can count on that. I know I would just join the two tables (usertable/messagetable) on the uniqueID, pull the message from the message table and the pull the username from the usertable.. But it seems performance would be greatly better, especially on larger recordsets to just use a single table...

I doubt you'd see a significant difference in the scenario you put forth.

I agree with Jethro, err nakedfrog.
 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
Originally posted by: BoberFett
Whatever you say. You already sound like you've made up your mind, so why ask here? Denormalize, but don't come back crying later when you discover that your "business rules that never change" have changed, and you have to now write triggers that update other tables because you didn't normalize.

You don't know whether OP has made up his mind, or if he has, whether he is wrong and you are right, given the context of his application. Invariant user id's is not such an uncommon business rule.

Anyway, I wouldn't denormalize unless testing shows that normal form is a performance problem.

 

imported_Dhaval00

Senior member
Jul 23, 2004
573
0
0
Originally posted by: BoberFett
Whatever you say. You already sound like you've made up your mind, so why ask here? Denormalize, but don't come back crying later when you discover that your "business rules that never change" have changed, and you have to now write triggers that update other tables because you didn't normalize.

Ignoring the tone )), there is truth in this - I see "username" more as serving the business need (similar to address, name, etc. columns). In order to ensure uniqueness, simply put a constraint on the username column. You can also create a non-clustered index if your queries are based on username.

However, since you're in control, do it properly from the get-go: Use an internal key and use that as your base for building queries. Assuming you have a clustered index on the primary [internal] key, you shouldn't have to worry about performance.

What is the primary purpose of your front-end? I ask because I see a lot of "denormalization" - mostly in data warehousing and reporting; if your primary need is to generate "uber-responsive" reports, then don't normalize. Again, approach this path with caution.
 
Oct 27, 2007
17,009
1
0
If you're running MS SQL Server 2008 I'd go for the normalized schema without a second thought. SQL Server 2008 has had some pretty big performance tweaks and it's likely that the DBMS is smarter than you are in terms of optimizing. Modern DBMSs are getting pretty smart.
 

JasonCoder

Golden Member
Feb 23, 2005
1,893
1
81
Originally posted by: GodlessAstronomer
If you're running MS SQL Server 2008 I'd go for the normalized schema without a second thought. SQL Server 2008 has had some pretty big performance tweaks and it's likely that the DBMS is smarter than you are in terms of optimizing. Modern DBMSs are getting pretty smart.

This.
 

BoberFett

Lifer
Oct 9, 1999
37,562
9
81
Originally posted by: Dhaval00
Originally posted by: BoberFett
Whatever you say. You already sound like you've made up your mind, so why ask here? Denormalize, but don't come back crying later when you discover that your "business rules that never change" have changed, and you have to now write triggers that update other tables because you didn't normalize.

Ignoring the tone )), there is truth in this - I see "username" more as serving the business need (similar to address, name, etc. columns). In order to ensure uniqueness, simply put a constraint on the username column. You can also create a non-clustered index if your queries are based on username.

However, since you're in control, do it properly from the get-go: Use an internal key and use that as your base for building queries. Assuming you have a clustered index on the primary [internal] key, you shouldn't have to worry about performance.

What is the primary purpose of your front-end? I ask because I see a lot of "denormalization" - mostly in data warehousing and reporting; if your primary need is to generate "uber-responsive" reports, then don't normalize. Again, approach this path with caution.

Yeah, sorry didn't mean to get snippy. But day in and day out I deal with people who ask for advice because I've got 15+ years of experience designing software, then they proceed to do things their own way instead and it almost invariably ends up biting them in the ass later. I guess I was projecting a bit onto the OP, my apologies. :beer:
 

brandonbull

Diamond Member
May 3, 2005
6,338
1,215
126
Originally posted by: BoberFett
Originally posted by: Dhaval00
Originally posted by: BoberFett
Whatever you say. You already sound like you've made up your mind, so why ask here? Denormalize, but don't come back crying later when you discover that your "business rules that never change" have changed, and you have to now write triggers that update other tables because you didn't normalize.

Ignoring the tone )), there is truth in this - I see "username" more as serving the business need (similar to address, name, etc. columns). In order to ensure uniqueness, simply put a constraint on the username column. You can also create a non-clustered index if your queries are based on username.

However, since you're in control, do it properly from the get-go: Use an internal key and use that as your base for building queries. Assuming you have a clustered index on the primary [internal] key, you shouldn't have to worry about performance.

What is the primary purpose of your front-end? I ask because I see a lot of "denormalization" - mostly in data warehousing and reporting; if your primary need is to generate "uber-responsive" reports, then don't normalize. Again, approach this path with caution.

Yeah, sorry didn't mean to get snippy. But day in and day out I deal with people who ask for advice because I've got 15+ years of experience designing software, then they proceed to do things their own way instead and it almost invariably ends up biting them in the ass later. I guess I was projecting a bit onto the OP, my apologies. :beer:

I feel your pain. I have to report on data from a system where the data is 100% designed for supporting the UI. They love to store string literal values and it's so much fun doing string searches and coding for different variations of spellings.
 
sale-70-410-exam    | Exam-200-125-pdf    | we-sale-70-410-exam    | hot-sale-70-410-exam    | Latest-exam-700-603-Dumps    | Dumps-98-363-exams-date    | Certs-200-125-date    | Dumps-300-075-exams-date    | hot-sale-book-C8010-726-book    | Hot-Sale-200-310-Exam    | Exam-Description-200-310-dumps?    | hot-sale-book-200-125-book    | Latest-Updated-300-209-Exam    | Dumps-210-260-exams-date    | Download-200-125-Exam-PDF    | Exam-Description-300-101-dumps    | Certs-300-101-date    | Hot-Sale-300-075-Exam    | Latest-exam-200-125-Dumps    | Exam-Description-200-125-dumps    | Latest-Updated-300-075-Exam    | hot-sale-book-210-260-book    | Dumps-200-901-exams-date    | Certs-200-901-date    | Latest-exam-1Z0-062-Dumps    | Hot-Sale-1Z0-062-Exam    | Certs-CSSLP-date    | 100%-Pass-70-383-Exams    | Latest-JN0-360-real-exam-questions    | 100%-Pass-4A0-100-Real-Exam-Questions    | Dumps-300-135-exams-date    | Passed-200-105-Tech-Exams    | Latest-Updated-200-310-Exam    | Download-300-070-Exam-PDF    | Hot-Sale-JN0-360-Exam    | 100%-Pass-JN0-360-Exams    | 100%-Pass-JN0-360-Real-Exam-Questions    | Dumps-JN0-360-exams-date    | Exam-Description-1Z0-876-dumps    | Latest-exam-1Z0-876-Dumps    | Dumps-HPE0-Y53-exams-date    | 2017-Latest-HPE0-Y53-Exam    | 100%-Pass-HPE0-Y53-Real-Exam-Questions    | Pass-4A0-100-Exam    | Latest-4A0-100-Questions    | Dumps-98-365-exams-date    | 2017-Latest-98-365-Exam    | 100%-Pass-VCS-254-Exams    | 2017-Latest-VCS-273-Exam    | Dumps-200-355-exams-date    | 2017-Latest-300-320-Exam    | Pass-300-101-Exam    | 100%-Pass-300-115-Exams    |
http://www.portvapes.co.uk/    | http://www.portvapes.co.uk/    |