| Version 3 (modified by , 2 weeks ago) ( diff ) |
|---|
# Нормализација
Де-нормализирана база на податоци
Се тргнува од една глобална, де-нормализирана релација што ги содржи атрибутите од целиот модел:
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, task_name, task_finished, daily_completion_id, daily_completion_date, daily_completion_percent, finance_user_id, finance_spending_budget, finance_saving_budget, finance_investing_budget, finance_donation_budget, finance_credit, income_id, income_date, income_amount }
Оваа релација е де-нормализирана затоа што содржи повторливи групи, како и зависности од атрибути што не се клуч.
Функционални зависности
- FD1:
user_id -> email, username, password - FD2:
email -> user_id, username, password - FD3:
username -> user_id, email, password - FD4:
training_user_id -> training_gender, training_age, training_weight - FD5:
training_id -> training_user_id, training_date, training_type, training_duration, training_calories - FD6:
investor_user_id -> user_id - FD7:
asset_id -> investor_user_id, asset_ticker_symbol, asset_buy_price, asset_buy_date, asset_quantity - FD8:
weight_user_id -> weight_current, weight_height, weight_goal_weight, weight_goal_calories - FD9:
daily_intake_id -> weight_user_id, daily_intake_date, daily_intake_calories - FD10:
discipline_user_id -> user_id - FD11:
custom_tracking_id -> user_id, custom_tracking_name - FD12:
task_id -> discipline_user_id, custom_tracking_id, task_name, task_finished - FD13:
daily_completion_id -> user_id, daily_completion_date, daily_completion_percent - FD14:
(task_id, daily_completion_id) -> / - FD15:
finance_user_id -> finance_spending_budget, finance_saving_budget, finance_investing_budget, finance_donation_budget, finance_credit - FD16:
income_id -> finance_user_id, income_date, income_amount
Леви и десен дел:
- Леви:
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 - Десен:
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, task_name, task_finished, daily_completion_date, daily_completion_percent, finance_spending_budget, finance_saving_budget, finance_investing_budget, finance_donation_budget, finance_credit, income_date, income_amount
Леви и десен дел:
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
Глобална релација
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, task_name, task_finished, daily_completion_id, daily_completion_date, daily_completion_percent, finance_user_id, finance_spending_budget, finance_saving_budget, finance_investing_budget, finance_donation_budget, finance_credit, income_id, income_date, income_amount }
Покривачи
user_id+= {user_id,email,username,password} -> не ги содржи сите атрибутиtraining_user_id+= {training_user_id,training_gender,training_age,training_weight} -> не ги содржи сите атрибутиtraining_id+= {training_id,training_user_id,training_date,training_type,training_duration,training_calories} -> не ги содржи сите атрибутиinvestor_user_id+= {investor_user_id,user_id} -> не ги содржи сите атрибутиasset_id+= {asset_id,investor_user_id,asset_ticker_symbol,asset_buy_price,asset_buy_date,asset_quantity} -> не ги содржи сите атрибутиweight_user_id+= {weight_user_id,weight_current,weight_height,weight_goal_weight,weight_goal_calories} -> не ги содржи сите атрибутиdaily_intake_id+= {daily_intake_id,weight_user_id,daily_intake_date,daily_intake_calories} -> не ги содржи сите атрибутиdiscipline_user_id+= {discipline_user_id,user_id} -> не ги содржи сите атрибутиcustom_tracking_id+= {custom_tracking_id,user_id,custom_tracking_name} -> не ги содржи сите атрибутиtask_id+= {task_id,discipline_user_id,custom_tracking_id,task_name,task_finished} -> не ги содржи сите атрибутиdaily_completion_id+= {daily_completion_id,user_id,daily_completion_date,daily_completion_percent} -> не ги содржи сите атрибутиfinance_user_id+= {finance_user_id,finance_spending_budget,finance_saving_budget,finance_investing_budget,finance_donation_budget,finance_credit} -> не ги содржи сите атрибутиincome_id+= {income_id,finance_user_id,income_date,income_amount} -> не ги содржи сите атрибути{task_id, daily_completion_id}+= {task_id,daily_completion_id} -> не ги содржи сите атрибути
Спојување покривачи
Бидејќи атрибутите што се појавуваат само на левата страна не можат да се изведат на друг начин, тие мора да бидат дел од примарниот клуч.
Земајќи ги сите леви атрибути заедно, добиваме минимален суперклуч:
{ 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 }
Во нашата нормализирана конструкција, ова е теоретскиот глобален кандидат-ключ на де-нормализираната релација.
Избран примарен клуч: { 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 }
Проверка за 1НФ
Бидејќи релацијата содржи повторливи групи и неатомски листи во де-нормализираниот поглед, не ја задоволува 1НФ.
Декомпозиција по 1НФ
Релација што се анализира
R
Проблем
Лист атрибутите и повторливите групи не се атомски.
Прва декомпозиција
TASKS(task_id, discipline_user_id, custom_tracking_id, task_name, task_finished)TASK_DAILY_COMPLETION(task_id, daily_completion_id)
Резултат
Се добиваат атомски вредности и релации со локални клучеви.
Проверка за 2НФ
R не ја задоволува 2НФ поради парцијални зависности, на пример:
user_id -> email, username, passwordtraining_user_id -> training_gender, training_age, training_weightasset_id -> asset_ticker_symbol, asset_buy_price, asset_buy_date, asset_quantity
Декомпозиција по 2НФ
Атрибутите се групираат според тоа од кој клуч зависат:
USERS(user_id, email, username, password)TRAINING_USERS(user_id, gender, age, weight)TRAINING_SESSIONS(training_id, training_user_id, date, type, duration, calories)INVESTOR_USERS(user_id)ASSETS(asset_id, user_id, ticker_symbol, buy_price, buy_date, quantity)WEIGHT_USERS(user_id, weight, height, goal_weight, goal_calories)DAILY_INTAKES(daily_intake_id, user_id, date, calories)DISCIPLINE_USERS(user_id)CUSTOM_TRACKING_CATEGORIES(custom_tracking_id, user_id, name)TASKS(task_id, discipline_user_id, custom_tracking_id, task_name, task_finished)DAILY_COMPLETION(daily_completion_id, user_id, date, procent)TASK_DAILY_COMPLETION(task_id, daily_completion_id)FINANCE_USERS(user_id, spending_budget, saving_budget, investing_budget, donation_budget, credit)INCOMES(income_id, user_id, date, amount)
Проверка за 3НФ
Ги разгледуваме релациите добиени по 2НФ.
Проблематични транзитивни/изведени атрибути се:
num_taskstasksweight_user_idвоTRAINING_SESSIONSкако непотребна зависност за оваа верзија на моделот
Декомпозиција по 3НФ
DISCIPLINE_USERS(user_id)-> се задржува само идентификаторот што ја врзува дисциплинската улога соUSERS.
CUSTOM_TRACKING_CATEGORIES(custom_tracking_id, user_id, name)-> се задржува само името на категоријата, без броење и листи на задачи.
TRAINING_SESSIONS(training_id, training_user_id, date, type, duration, calories)-> сесијата се врзува само соtraining_user_id.
Резултат
Нема не-клучен атрибут што зависи од друг не-клучен атрибут во истата релација.
Проверка за БКНФ
Сите добиени релации се во БКНФ, бидејќи секој детерминант е кандидат-ключ во својата релација.
Особено:
USERSги задржува алтернативните клучевиemailиusernameTASK_DAILY_COMPLETION(task_id, daily_completion_id)е спојна релација без не-клучни атрибути- профилните релации со
user_idсе чисти 1:1 продолжувања наUSERS
Финален резултат и дискусија
Нормализиран релациски модел
Финалниот модел што го користиме во тековната имплементација е:
USERSTRAINING_USERSTRAINING_SESSIONSINVESTOR_USERSASSETSWEIGHT_USERSDAILY_INTAKESDISCIPLINE_USERSCUSTOM_TRACKING_CATEGORIESTASKSDAILY_COMPLETIONTASK_DAILY_COMPLETIONFINANCE_USERSINCOMES
Дискусија
Разлики во однос на претходниот дизајн:
- Се отстранети
num_tasksиtasksод дисциплинските табели. - Се отстранета непотребната релација
weight_user_idодTRAINING_SESSIONS. - Се задржуваат профилните табели со
user_idкако заеднички примарен и странски клуч.
Одлука за следните фази:
- Овој нормализиран модел останува извор на вистина.
- API форматот може да остане стабилен, додека внатрешната шема е нормализирана.
- DDL и DML скриптите треба да ја следат оваа шема.
