title: Information System DB Design description: > Things to keep in mind when designing a database for an information system categories: posts
Table of Contents
Although the focus of this article is DB design here are some things to consider from the requirements:
Identify
Model
A table may stand for
Also, consider
From the first schema implementation we should test our table, and associations designs using sample/fake data.
We should iterate over table, and association designs to avoid modifying their attributes once in production.
Relevant Sequel pages:
Also, since test data hardly ever produces the best optimizations for real data we should avoid creating indexes, and the like, during testing.
Like DB tables, associations also stand for concepts in the problem domain. They are used to simplify the code that deals with related tuples in separate DB tables.
We can only associate DB tables which share key attributes.
We enforce uniqueness by assigning an attribute as the key. Whenever we need to use more than one attribute to differentiate each tuple we call it a composite key.
A table's unique identifier is called primary key. To assign a primary key to a table we need to identify (in order)
On every association, one of the tables has to hold the primary key of the other. Although is meant to connect tuples in different tables it's called foreign key.
To avoid orphaned tuples across tables, whenever we delete a tuple from any of the tables in an association we must either:
Two tables are in a many-to-one (*-1
) association when zero, one, or
more tuples in one table are associated to a single tuple in a different
table.
| albums | | artists |
|------------| |---------|
| :id | /---1- | :id |
| :artist_id | -*---/ | :name |
| :name |
Using Ruby's Sequel toolkit
class Album < Sequel::Model
many_to_one :artist
end
Two tables are in a one-to-many (1-*
) association when every tuple in
one table is associated with zero, one, or more tuples in another table.
| artists | | albums |
|---------| |------------|
| :id | -1---\ | :id |
| :name | \--*- | :artist_id |
| :name |
This association is complimentary to many-to-one. Using Sequel,
class Artist < Sequel::Model
one_to_many :albums
end
A one-to-one (1—1
) association may be necessary when we have to split a
table into two or more tables for security or performance reasons.
| users | | phrases |
|---------| |----------|
| :id | -1---\ | :phrase |
| :email | \--1- | :user_id |
This is considered a subset of the one-to-many association.
class Artist < Sequel::Model
one_to_one :album
end
A many-to-many association (*-*
) allows each tuple in a table to be
associated to many tuples in an associated table, and vice versa.
| albums | | artists |
|------------| |---------|
| :id | /---*- | :id |
| :artist_id | -*---/ | :name |
| :name |
To satisfy both conditions, this association is broken into two one-to-many associations using a joined table to associate them.
| albums | | albums_artists | | artists |
|--------| |----------------| |---------|
| :id | -1-\ | :album_id | /-1- | :id |
| :name | \-*- | :artist_id | -*-/ | :name |
Using Sequel, and assuming the albums_artist
table exists
class Artist < Sequel::Model
many_to_many :albums
end
The one-through-one association sets up a one-to-one association through a joined table.
The difference between the one-through-one, and many-to-many association is that in the former there can only be 0 or 1 records in the associated table.
This association is useful for
Using Sequel
class Artist < Sequel::Model
one_through_one :album
end
Normalization is a way to organize data. There are various normal forms, each dependent on the previous one.
It's usually easier to apply the 1st form in this order
All attributes must be related to the primary key. Extract any attribute which doesn't refer to the primary key, into it's own table.
Remove transitive dependencies:
There are other four normal forms. Beware, the more we normalize, the
more we decompose our data into smaller tables. Which could make it
difficult to write queries due to multiple Join
.
Although we make reference to a composite key in forms 4 and 5, at that point those should be the only attributes in the relation.
Some of the techniques we can use for data integrity are:
Sequel relevant documentation:
A transaction is the execution of several operations considered a unit of work. A transaction is consider reliable when it has these properties
Sequel relevant links:
Once the system has been in production for a while we should analyse DB statistics to improve the DB performance. Consider using features such as
Keep in mind that some DBMS, such as postgres, provide details of their implementations so we can use the best one according to our needs.
Sequel relevant links