Reputation: 8200
Suppose I have a products table. Some products have a fee associated with them. Those fees can change from time to time, but I need to know what that fee is for any given time.
My initial design included:
| products |
|----------|
| id |
| name |
| fees |
|----------------|
| id |
| amount |
| effective_from |
| effective_to |
| product_id |
Sample Fees table:
| id | amount | effective_from | effective_to | product_id |
|----|--------|----------------|--------------|------------|
| 1 | 20 | 2015-01-01 | 2015-06-01 | 1 |
| 2 | 25 | 2015-06-01 | 2015-09-01 | 1 |
| 3 | 27 | 2015-09-01 | NULL | 1 |
Benefits:
Simple Query to fetch applicable fee:
WHERE $date < effective_to AND $date > effective_from;
Downsides:
row 1 effective_to = row 2 effective_from
row 1 effective_to != row 2 effective_from
Alternative design:
| fees |
|----------------|
| id |
| amount |
| effective_from |
| product_id |
Sample Fees table:
| id | amount | effective_from | product_id |
|----|--------|----------------|------------|
| 1 | 20 | 2015-01-01 | 1 |
| 2 | 25 | 2015-06-01 | 1 |
| 3 | 27 | 2015-09-01 | 1 |
Benefits:
Still easy to query:
WHERE effective_from < $date ORDER BY effective_from DESC LIMIT 1;
Downsides:
Which should I use? Does anyone have a better suggestion? Thanks for sticking with me!
Upvotes: 0
Views: 40
Reputation: 142298
Given INDEX(effective_from)
, the second design will be much more performant because it needs to touch only the one row. The first design needs to scan, on average, half the table.
Upvotes: 1
Reputation: 52346
Have you benchmarked the performance of any queries that find the appropriate row based only on the effective_from date?
I think you'll find that they are not as inefficient in comparison to the other as you might guess, as the best optimisation for either one is to scan an index on id and effective_from.
I would always go for the second design -- databases are better at querying than they are at enforcing intra-row constraints.
Upvotes: 1