I am working on a database which has some types (e.g. User
, Appointment
, Task
etc.) which can have zero or more Notes
associated with each type.
The possible solutions I have come across for implementing these relationships are:
- Polymorphic relationship
- Separate table per type
Polymorphic Relationship
Suggested by many as being the easiest solution to implement and seemingly the most common implementation for frameworks that follow the Active Record pattern, I would add a table whose data is morphable
:
My notable_type
would allow me to distinguish between the type (User
, Appointment
, Task
) the Note
relates to, whilst the notable_id
would allow me to obtain the individual type
record in the related type
table.
PROS:
- Easy to scale, more models can be easily associated with the polymorphic class
- Limits table bloat
- Results in one class that can be used by many other classes (DRY)
CONS
- More types can make querying more difficult and expensive as the data grows
- Cannot have a foreign key
- Lack of data consistency
Separate Table per Type
Alternatively I could create a table for each type which is responsible for the Notes
associated with that type only. The type_id
foreign key would allow me to quickly obtain the individual type
record.
Deemed by many online as a code smell, many articles advocate avoiding the polymorphic relationship in favour of an alternative (here and here for example).
PROS:
- Allows us to use foreign keys effectively
- Efficient data querying
- Maintains data consistency
CONS:
- Increases table bloat as each type requires a separate table
- Results in multiple classes, each representing the separate
type_notes
table
Thoughts
The polymorphic relationship is certainly the simpler of the two options to implement, but the lack of foreign key constraints and therefore potential for consistency issues feels wrong.
A table per notes
relationship (user_notes
, task_notes
etc.) with foreign keys seems the correct way (in keeping with design patterns) but could result in a lot of tables (addition of other types
that can have notes
or addition of types similar to notes
[e.g. events
]).
It feels like my choice is either simplified table structure but forgo foreign keys and increased query overhead, or increase the number of tables with the same structure but simplify queries and allow for foreign keys.
Given my scenario which of the above would be more appropriate, or is there an alternative I should consider?