source: backend/docs/Normalization.txt@ c4c43f3

Last change on this file since c4c43f3 was c4c43f3, checked in by Andrej <asumanovski@…>, 3 months ago

Normalization of the database

  • Property mode set to 100644
File size: 12.5 KB
Line 
1# **Нормализација**
2
3== **Де-нормализирана база на податоци**
4
5Се тргнува од една глобална, де-нормализирана релација што ги содржи атрибутите од целиот модел:
6
7`R = { user_id, email, username, password, training_user_id, training_gender, training_age, training_weight, training_id, training_date, training_type, training_duration, training_calories, investor_user_id, asset_id, asset_ticker_symbol, asset_buy_price, asset_buy_date, asset_quantity, weight_user_id, weight_current, weight_height, weight_goal_weight, weight_goal_calories, daily_intake_id, daily_intake_date, daily_intake_calories, discipline_user_id, custom_tracking_id, custom_tracking_name, task_id, name, is_finished, daily_completion_id, daily_completion_date, procent, finance_user_id, finance_spending_budget, finance_saving_budget, finance_investing_budget, finance_donation_budget, finance_credit, income_id, income_date, income_amount }`
8
9Оваа релација е де-нормализирана затоа што содржи повторливи групи, како и зависности од атрибути што не се клуч.
10
11== **Функционални зависности**
12
13- **FD1:** `user_id -> email, username, password`
14- **FD2:** `email -> user_id, username, password`
15- **FD3:** `username -> user_id, email, password`
16- **FD4:** `training_user_id -> training_gender, training_age, training_weight`
17- **FD5:** `training_id -> training_user_id, training_date, training_type, training_duration, training_calories`
18- **FD6:** `investor_user_id -> user_id`
19- **FD7:** `asset_id -> investor_user_id, asset_ticker_symbol, asset_buy_price, asset_buy_date, asset_quantity`
20- **FD8:** `weight_user_id -> weight_current, weight_height, weight_goal_weight, weight_goal_calories`
21- **FD9:** `daily_intake_id -> weight_user_id, daily_intake_date, daily_intake_calories`
22- **FD10:** `discipline_user_id -> user_id`
23- **FD11:** `custom_tracking_id -> user_id, custom_tracking_name`
24- **FD12:** `task_id -> discipline_user_id, custom_tracking_id, name, is_finished`
25- **FD13:** `daily_completion_id -> user_id, daily_completion_date, procent`
26- **FD14:** `(task_id, daily_completion_id) -> /`
27- **FD15:** `finance_user_id -> finance_spending_budget, finance_saving_budget, finance_investing_budget, finance_donation_budget, finance_credit`
28- **FD16:** `income_id -> finance_user_id, income_date, income_amount`
29
30**Леви и десен дел:**
31
32- **Леви:** `user_id, email, username, training_user_id, training_id, investor_user_id, asset_id, weight_user_id, daily_intake_id, discipline_user_id, custom_tracking_id, task_id, daily_completion_id, finance_user_id, income_id`
33- **Десен:** `password, training_gender, training_age, training_weight, training_date, training_type, training_duration, training_calories, asset_ticker_symbol, asset_buy_price, asset_buy_date, asset_quantity, weight_current, weight_height, weight_goal_weight, weight_goal_calories, daily_intake_date, daily_intake_calories, custom_tracking_name, name, is_finished, daily_completion_date, procent, finance_spending_budget, finance_saving_budget, finance_investing_budget, finance_donation_budget, finance_credit, income_date, income_amount`
34
35== **Глобална релација**
36
37`R = { user_id, email, username, password, training_user_id, training_gender, training_age, training_weight, training_id, training_date, training_type, training_duration, training_calories, investor_user_id, asset_id, asset_ticker_symbol, asset_buy_price, asset_buy_date, asset_quantity, weight_user_id, weight_current, weight_height, weight_goal_weight, weight_goal_calories, daily_intake_id, daily_intake_date, daily_intake_calories, discipline_user_id, custom_tracking_id, custom_tracking_name, task_id, name, is_finished, daily_completion_id, daily_completion_date, procent, finance_user_id, finance_spending_budget, finance_saving_budget, finance_investing_budget, finance_donation_budget, finance_credit, income_id, income_date, income_amount }`
38
39== **Покривачи**
40
41- **`user_id+`** = { `user_id`, `email`, `username`, `password` } -> **не ги содржи сите атрибути**
42- **`training_user_id+`** = { `training_user_id`, `training_gender`, `training_age`, `training_weight` } -> **не ги содржи сите атрибути**
43- **`training_id+`** = { `training_id`, `training_user_id`, `training_date`, `training_type`, `training_duration`, `training_calories` } -> **не ги содржи сите атрибути**
44- **`investor_user_id+`** = { `investor_user_id`, `user_id` } -> **не ги содржи сите атрибути**
45- **`asset_id+`** = { `asset_id`, `investor_user_id`, `asset_ticker_symbol`, `asset_buy_price`, `asset_buy_date`, `asset_quantity` } -> **не ги содржи сите атрибути**
46- **`weight_user_id+`** = { `weight_user_id`, `weight_current`, `weight_height`, `weight_goal_weight`, `weight_goal_calories` } -> **не ги содржи сите атрибути**
47- **`daily_intake_id+`** = { `daily_intake_id`, `weight_user_id`, `daily_intake_date`, `daily_intake_calories` } -> **не ги содржи сите атрибути**
48- **`discipline_user_id+`** = { `discipline_user_id`, `user_id` } -> **не ги содржи сите атрибути**
49- **`custom_tracking_id+`** = { `custom_tracking_id`, `user_id`, `custom_tracking_name` } -> **не ги содржи сите атрибути**
50- **`task_id+`** = { `task_id`, `discipline_user_id`, `custom_tracking_id`, `name`, `is_finished` } -> **не ги содржи сите атрибути**
51- **`daily_completion_id+`** = { `daily_completion_id`, `user_id`, `daily_completion_date`, `procent` } -> **не ги содржи сите атрибути**
52- **`finance_user_id+`** = { `finance_user_id`, `finance_spending_budget`, `finance_saving_budget`, `finance_investing_budget`, `finance_donation_budget`, `finance_credit` } -> **не ги содржи сите атрибути**
53- **`income_id+`** = { `income_id`, `finance_user_id`, `income_date`, `income_amount` } -> **не ги содржи сите атрибути**
54- **`{task_id, daily_completion_id}+`** = { `task_id`, `daily_completion_id` } -> **не ги содржи сите атрибути**
55
56== **Спојување покривачи**
57
58Бидејќи атрибутите што се појавуваат само на левата страна не можат да се изведат на друг начин, тие мора да бидат дел од примарниот клуч.
59
60Земајќи ги сите леви атрибути заедно, добиваме минимален суперклуч:
61
62`{ user_id, training_user_id, training_id, investor_user_id, asset_id, weight_user_id, daily_intake_id, discipline_user_id, custom_tracking_id, task_id, daily_completion_id, finance_user_id, income_id }`
63
64Во нашата нормализирана конструкција, ова е теоретскиот глобален кандидат-клуч на де-нормализираната релација.
65
66Избран примарен клуч: **`{ user_id, training_user_id, training_id, investor_user_id, asset_id, weight_user_id, daily_intake_id, discipline_user_id, custom_tracking_id, task_id, daily_completion_id, finance_user_id, income_id }`**
67
68== **Проверка за 1НФ**
69
70Бидејќи релацијата содржи повторливи групи и неатомски листи во де-нормализираниот поглед, **не ја задоволува 1НФ**.
71
72== **Декомпозиција по 1НФ**
73
74**Релација што се анализира**
75
76`R`
77
78**Проблем**
79
80Лист атрибутите и повторливите групи не се атомски.
81
82**Прва декомпозиција**
83
84- `TASKS(task_id, discipline_user_id, custom_tracking_id, name, is_finished)`
85- `TASK_DAILY_COMPLETION(task_id, daily_completion_id)`
86
87**Резултат**
88
89Се добиваат атомски вредности и релации со локални клучеви.
90
91== **Проверка за 2НФ**
92
93`R` **не ја задоволува 2НФ** поради парцијални зависности, на пример:
94
95- `user_id -> email, username, password`
96- `training_user_id -> training_gender, training_age, training_weight`
97- `asset_id -> asset_ticker_symbol, asset_buy_price, asset_buy_date, asset_quantity`
98
99== **Декомпозиција по 2НФ**
100
101Атрибутите се групираат според тоа од кој клуч зависат:
102
103- **`USERS(user_id, email, username, password)`**
104- **`TRAINING_USERS(user_id, gender, age, weight)`**
105- **`TRAINING_SESSIONS(training_id, training_user_id, date, type, duration, calories)`**
106- **`INVESTOR_USERS(user_id)`**
107- **`ASSETS(asset_id, user_id, ticker_symbol, buy_price, buy_date, quantity)`**
108- **`WEIGHT_USERS(user_id, weight, height, goal_weight, goal_calories)`**
109- **`DAILY_INTAKES(daily_intake_id, user_id, date, calories)`**
110- **`DISCIPLINE_USERS(user_id)`**
111- **`CUSTOM_TRACKING_CATEGORIES(custom_tracking_id, user_id, name)`**
112- **`TASKS(task_id, discipline_user_id, custom_tracking_id, name, is_finished)`**
113- **`DAILY_COMPLETION(daily_completion_id, user_id, date, procent)`**
114- **`TASK_DAILY_COMPLETION(task_id, daily_completion_id)`**
115- **`FINANCE_USERS(user_id, spending_budget, saving_budget, investing_budget, donation_budget, credit)`**
116- **`INCOMES(income_id, user_id, date, amount)`**
117
118== **Проверка за 3НФ**
119
120Ги разгледуваме релациите добиени по 2НФ.
121
122Проблематични транзитивни/изведени атрибути се:
123
124- **`num_tasks`**
125- **`tasks`**
126- **`weight_user_id`** во `TRAINING_SESSIONS` како непотребна зависност за оваа верзија на моделот
127
128== **Декомпозиција по 3НФ**
129
1301. **`DISCIPLINE_USERS(user_id)`** -> се задржува само идентификаторот што ја врзува дисциплинската улога со `USERS`.
131
1322. **`CUSTOM_TRACKING_CATEGORIES(custom_tracking_id, user_id, name)`** -> се задржува само името на категоријата, без броење и листи на задачи.
133
1343. **`TRAINING_SESSIONS(training_id, training_user_id, date, type, duration, calories)`** -> сесијата се врзува само со `training_user_id`.
135
136**Резултат**
137
138Нема не-клучен атрибут што зависи од друг не-клучен атрибут во истата релација.
139
140== **Проверка за БКНФ**
141
142Сите добиени релации се во БКНФ, бидејќи секој детерминант е кандидат-клуч во својата релација.
143
144Особено:
145
146- **`USERS`** ги задржува алтернативните клучеви `email` и `username`
147- **`TASK_DAILY_COMPLETION(task_id, daily_completion_id)`** е спојна релација без не-клучни атрибути
148- профилните релации со `user_id` се чисти 1:1 продолжувања на `USERS`
149
150== **Финален резултат и дискусија**
151
152== **Нормализиран релациски модел**
153
154Финалниот модел што го користиме во тековната имплементација е:
155
156- **`USERS`**
157- **`TRAINING_USERS`**
158- **`TRAINING_SESSIONS`**
159- **`INVESTOR_USERS`**
160- **`ASSETS`**
161- **`WEIGHT_USERS`**
162- **`DAILY_INTAKES`**
163- **`DISCIPLINE_USERS`**
164- **`CUSTOM_TRACKING_CATEGORIES`**
165- **`TASKS`**
166- **`DAILY_COMPLETION`**
167- **`TASK_DAILY_COMPLETION`**
168- **`FINANCE_USERS`**
169- **`INCOMES`**
170
171== **Дискусија**
172
173Разлики во однос на претходниот дизајн:
174
175- Се отстранети **`num_tasks`** и **`tasks`** од дисциплинските табели.
176- Се отстранета непотребната релација **`weight_user_id`** од `TRAINING_SESSIONS`.
177- Се задржуваат профилните табели со **`user_id`** како заеднички примарен и странски клуч.
178
179Одлука за следните фази:
180
181- **Овој нормализиран модел** останува извор на вистина.
182- **API форматот** може да остане стабилен, додека внатрешната шема е нормализирана.
183- **DDL и DML скриптите** треба да ја следат оваа шема.
Note: See TracBrowser for help on using the repository browser.