1

I am designing a database for a system that has a users table. Currently, the table has around 50 columns, which include:

  • Personal information (e.g., name, email, phone_number, address, etc.)
  • Work-related information (e.g., job_title, company_name, years_experience, etc.)
  • Education-related information (e.g., degree, institution, graduation_year, etc.)

Some of these columns are only applicable to specific roles, like employees or students, while others are common to all users. I’m considering breaking the users table into smaller tables, such as:

  • A main users table for general information.
  • A work_experiences table for job-related details.
  • An education table for academic details.

My question is:

Is splitting the users table into smaller tables based on their context (work, education, etc.) a good practice?

I’m using MySQL, and performance is a concern since the system will scale to thousands of users.

Thank you for your advice!

New contributor
JayDev95 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
1
  • 1
    Might also want to consider have address be its own table, as well as email and phone (contact info). If you are sending out notifications to users, this will help customize what method and what number to contact them (phone, text, mail, etc.). This makes it easy to users to have multiple addresses and contact points in the system.
    – Jon Raynor
    Commented 2 days ago

3 Answers 3

2

Breaking a large user table into smaller, context-specific tables is generally considered a good practice in database design. This approach follows the principles of database normalization, which helps organize data to reduce redundancy, improve scalability, and enhance query performance.

You could normalize your tables as follows:

Entity: User

Attributes:
    id: int
    name: str
    email: str
    phone_number: str
    address: str

Entity: WorkExperience

Attributes:
    id: int
    user_id: int (foreign key to User)
    job_title: str
    company_name: str
    years_experience: int

Entity: Education

Attributes:
    id: int
    user_id: int (foreign key to User)
    degree: str
    institution: str
    graduation_year: int

the gist of it is for entities work_experience and education to reference their related user. This makes maintaining the tables easy as you can update one without affecting the other.

New contributor
user459797 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
4

You should break the table up based one what is 1-to-many relationships. For example a user might have more than one degree, so education should be a separate table from user, with a foreign key to user. This allows a user to have 0 or multiple degrees.

You should not break tables up purely on context, if the tables end up having a strict 1:1 relationship. This will just make insertion and deletion unnecessary complex and error prone.

-2

As opposed to another answer: no, you should not.

Normalization is a principle invented in a time where storage was expensive, and is used for space-optimization as opposed to time optimization.

If you need speed (and you say you do), denormalize. Put all the data in a single table, read all columns in a single table query.

Basically:

Querying a single table is fastest select * from users where ...

Querying multiple tables in a join is slightly slower

select
  *
from
  users u
  join work_info wi on  ...
  join education e on ...
where 
  ...
  

You don't have any advantage doing this it this way, as you still query exactly the same columns, you just put more load on the database.

Doing multiple separate queries is the slowest you can do:

select * from users where ...

if (user.isStudent)
    select ... from education ...
     
if (user.isWhatever)
    select ... from work_info ...

As you will have multiple separate interchanges between application code and database. Networks are slow compared to processors.

So, for speed, keep it in one table.

3
  • 5
    The purpose of normalization is not space-optimization. (Indeed normalization might require more space for some datasets since you introduce a foreign-key column.) The purpose of normalization is to avoid inconsistent data, which is a form of data corruption.
    – JacquesB
    Commented Dec 10 at 7:04
  • @JacquesB It is probably a mixture of both. However, the argument of consistency only makes sense, if data is actually being reused. In a tree structure, like the OP describes it, there is no consistency to maintain. You simply split a single object graph into multiple tables. (As opposed to your answer, I see education as non-reusable, as the combination of institutes and marks seems very individual to me.)
    – mtj
    Commented Dec 10 at 7:13
  • 3
    Inconsistency may happen when you have a one-to-many relationship expressed in the same table. E.g. if you represent the result of the join in the first example as a single table, the user data will be repeated for each education (assuming a user may have more than one degree). Now there is a risk of these repetitions to get out of sync, e.g. due to a botched update.
    – JacquesB
    Commented Dec 10 at 7:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.