Normalisation (ဒေတာ ထပ်မနေအောင် table တွေကို စီစဉ်ခြင်း)
A3.2.5: Explain the difference between normal forms (1NF, 2NF, 3NF). A3.2.6: Construct a database normalised to 3NF for a range of real-world scenarios. A3.2.7: Evaluate the need for denormalising databases.
မြန်မာလို: A3.2.5: normal form (table တွေ ပြည့်မီရမယ့် စံ အဆင့်) တွေ ဖြစ်တဲ့ 1NF (ပထမ normal form)၊ 2NF (ဒုတိယ normal form) နဲ့ 3NF (တတိယ normal form) တို့ကြားက ကွာခြားချက်ကို ရှင်းပြနိုင်ရပါမယ်။ A3.2.6: လက်တွေ့ဘဝက အခြေအနေ အမျိုးမျိုးအတွက် 3NF အထိ normalise လုပ်ထားတဲ့ database (ဒေတာ သိမ်းဆည်းတဲ့ စနစ်) ကို ကိုယ်တိုင် တည်ဆောက်နိုင်ရပါမယ်။ A3.2.7: database တွေကို denormalise (ဖတ်တာ မြန်အောင် ထပ်နေမှုကို တမင် ပြန်ထည့်) လုပ်ဖို့ လိုမလို အကဲဖြတ်နိုင်ရပါမယ်။ ဒါတွေက IB Computer Science (နိုင်ငံတကာ ကျောင်းတွေမှာ သင်တဲ့ ကွန်ပျူတာသိပ္ပံ သင်ရိုး) ထဲက ခေါင်းစဉ် နံပါတ်တွေပါ။
- Normalise ဘာကြောင့် လုပ်ရသလဲ: table (database ထဲက ဇယား) ကြီး တစ်ခုတည်းမှာ ဒေတာတွေ ထပ်နေတာကြောင့် row (အလျားလိုက် အတန်း) တွေကို ပြင်တဲ့အခါ၊ ထည့်တဲ့အခါ၊ ဖယ်ရှားတဲ့အခါ ပြဿနာတွေ ဖြစ်ပါတယ်။ ဒါတွေကို update anomaly, insert anomaly နဲ့ delete anomaly လို့ ခေါ်ပါတယ်။
- Dependency (မှီခိုမှု) များ: partial-key dependency ဆိုတာ key (row တစ်ခုချင်းကို ခွဲခြားပေးတဲ့ တန်ဖိုး) ရဲ့ အပိုင်း တစ်ခုပေါ်မှာပဲ မှီခိုတာ ဖြစ်ပြီး transitive dependency ဆိုတာ key ထဲမှာ မပါတဲ့ တခြား column (ဒေါင်လိုက် ကော်လံ) တစ်ခုပေါ် မှီခိုတာပါ။
- 1NF, 2NF နဲ့ 3NF: 1NF မှာ cell (ဇယား အကွက်) တိုင်းမှာ တန်ဖိုး တစ်ခုတည်းပဲ ရှိရပါမယ်၊ 2NF မှာ partial-key dependency မရှိရပါဘူး၊ 3NF မှာ transitive dependency မရှိရပါဘူး။
- Denormalisation ကို အကဲဖြတ်ခြင်း: redundancy (ဒေတာ ထပ်နေမှု) ကို ပြန်ထည့်လိုက်ရင် ဖတ်တာ များတဲ့ စနစ်တွေ ပိုမြန်လာနိုင်ပေမယ့် update anomaly တွေ ပြန်ဖြစ်လာပါတယ်။
အဓိက အယူအဆများ
Normalisation ဆိုတာ ဘာလဲ
Normalisation (ဒေတာ ထပ်မနေအောင် table တွေကို စီစဉ်ခြင်း) ဆိုတာ relational database (table တွေ ချိတ်ဆက်ထားတဲ့ database) တစ်ခုရဲ့ column တွေကို table တွေထဲ စီစဉ်ပေးတဲ့ လုပ်ငန်းစဉ်ပါ။ ဒီလို စီစဉ်တာက လက်တွေ့ကမ္ဘာက အချက် တစ်ခုချင်းစီကို နေရာ တစ်ခုတည်းမှာပဲ အတိအကျ သိမ်းဖို့ပါ။ ရလဒ်အနေနဲ့ နေရာတိုင်းမှာ တန်ဖိုးတွေ ထပ်နေတဲ့ table ကြီး တစ်ခုအစား key တွေနဲ့ ချိတ်ထားပြီး အကြောင်းအရာ တစ်ခုစီကိုပဲ သိမ်းတဲ့ table အသေးလေးတွေ ရလာပါတယ်။
Database တစ်ခုကို normalise လုပ်တာကို အဆင့်ဆင့် လုပ်ရပါတယ်။ အဆင့်တိုင်းက အရင်အဆင့်ထက် ပိုတင်းကျပ်တဲ့ ဖွဲ့စည်းပုံကို ရစေပါတယ်:
- First Normal Form (1NF): atomic value (ထပ်ခွဲလို့ မရတဲ့ တန်ဖိုး တစ်ခုတည်း) တွေပဲ ပါရပါမယ်၊ repeating group (ထပ်ခါထပ်ခါ ပါနေတဲ့ column အုပ်စု) မရှိရပါဘူး၊ row တိုင်းကို တစ်ခုချင်း ခွဲခြားသိနိုင်ရပါမယ်
- Second Normal Form (2NF): 1NF ဖြစ်ပြီး partial-key dependency လည်း မရှိရပါဘူး
- Third Normal Form (3NF): 2NF ဖြစ်ပြီး transitive dependency လည်း မရှိရပါဘူး
3NF ဖြစ်တဲ့ database က လက်တွေ့ သုံးနေတဲ့ စနစ် အများစုရဲ့ database design အတွက် စံ ပန်းတိုင် ဖြစ်ပါတယ်။ ဒီထက် မြင့်တဲ့ normal form တွေ (BCNF, 4NF, 5NF) လည်း ရှိပေမယ့် လက်တွေ့မှာ လိုအပ်ခဲပါတယ်။
Normalise ဘာကြောင့် လုပ်ရသလဲ
အဖွဲ့ဝင်တွေကို စိုက်ကွက် (plot) တွေ ငှားပေးတဲ့ ရပ်ကွက် ဥယျာဉ် (community garden) တစ်ခုကို စဉ်းစားကြည့်ပါ။ ဥယျာဉ်ရဲ့ ကော်မတီက စည်းမျဉ်း ငါးခုအတိုင်း လုပ်ဆောင်ပါတယ်:
- စိုက်ကွက် တစ်ကွက်ချင်းစီမှာ နံပါတ် (
PlotID) တစ်ခုနဲ့ စတုရန်းမီတာနဲ့ တိုင်းတဲ့ အရွယ်အစား (SizeM2) ရှိပြီး ဥယျာဉ်ထဲက ဇုန် (zone) တစ်ခုထဲမှာ ရှိပါတယ်။ - ဇုန် တစ်ခုချင်းစီမှာ code (
ZoneCode) တစ်ခုနဲ့ နာမည် (ZoneName) တစ်ခုတည်း ရှိပါတယ်။ - ရာသီ (season) တစ်ခုစီမှာ (ပြက္ခဒိန် တစ်နှစ်၊
SeasonYear) စိုက်ကွက် တစ်ကွက်ကို စိုက်ပျိုးသူ (gardener) အများဆုံး တစ်ယောက်ကိုပဲ ငှားပါတယ်။ စိုက်ပျိုးသူ တစ်ယောက်က စိုက်ကွက် အများကြီး ငှားနိုင်ပြီး စိုက်ကွက် တစ်ကွက်ကို ရာသီ တစ်ခုနဲ့ တစ်ခု မတူတဲ့ စိုက်ပျိုးသူ ငှားနိုင်ပါတယ်။ - စိုက်ပျိုးသူ တစ်ယောက်ချင်းစီမှာ ID (
GardenerID) တစ်ခု၊ နာမည် တစ်ခုနဲ့ အဖွဲ့ဝင် အမျိုးအစား (membership type) တစ်မျိုးတည်း ရှိပါတယ်။ စိုက်ပျိုးသူ နှစ်ယောက်မှာ နာမည် တူနိုင်ပါတယ်။ - အဖွဲ့ဝင် အမျိုးအစား တစ်ခုချင်းစီ (Full, Junior ဒါမှမဟုတ် Senior) က အဲဒီ အမျိုးအစား အဖွဲ့ဝင်တွေ ရာသီတိုင်း လုပ်ရမယ့် ဥယျာဉ် တာဝန် နာရီ (
DutyHours) ကို သတ်မှတ်ပါတယ်။ တာဝန်ဆိုတာ အများသုံး လမ်းလျှောက်လမ်းတွေက ပေါင်းပင် နုတ်တာမျိုးပါ။
ရာသီတိုင်း ကော်မတီက စာရင်းသွင်း စာရွက် (sign-up sheet) တစ်ခုကို ဖြည့်ပါတယ်။ စိုက်ပျိုးသူ တစ်ယောက်ကို row တစ်ကြောင်းစီ ပါပါတယ်:
SIGNUP (unnormalised: normalise မလုပ်ရသေးတဲ့ table)
| SeasonYear | GardenerID | GardenerName | MemberType | DutyHours | PlotsRented |
|---|---|---|---|---|---|
| 2025 | G11 | Ivy Chen | Full | 10 | “3: 40 m², N North Field; 4: 40 m², N North Field” |
| 2025 | G15 | Ruth Okoro | Senior | 6 | “7: 60 m², E East Bank” |
| 2026 | G11 | Ivy Chen | Full | 10 | “3: 40 m², N North Field” |
| 2026 | G12 | Tomás Silva | Junior | 4 | “4: 40 m², N North Field; 7: 60 m², E East Bank” |
ဒီ table မှာ ပြဿနာတွေ အများကြီး ရှိပါတယ်:
| ပြဿနာ | ဥပမာ |
|---|---|
| Data duplication (ဒေတာ ထပ်နေခြင်း) | Ivy ရဲ့ နာမည်၊ အဖွဲ့ဝင် အမျိုးအစားနဲ့ တာဝန် နာရီတွေကို သူ စာရင်းသွင်းတဲ့ ရာသီတိုင်းမှာ ထပ်ရေးထားပါတယ်။ “N North Field” ကိုလည်း ဇုန် N ထဲက စိုက်ကွက် တိုင်းအတွက် ထပ်ရေးထားပါတယ်။ |
| Multi-valued cells (တန်ဖိုး အများ ပါတဲ့ cell) | PlotsRented ထဲမှာ စာရင်း တစ်ခု ပါနေပြီး အဲဒီ စာရင်းထဲက item တစ်ခုချင်းစီမှာ အချက် လေးခုကို ပေါင်းထည့်ထားပါတယ်: စိုက်ကွက် နံပါတ်၊ သူ့ အရွယ်အစား၊ ဇုန် code နဲ့ ဇုန် နာမည်။ |
| Update anomaly | ကော်မတီက ဇုန် N ကို နာမည်ပြောင်းရင် စာရွက်ပေါ်က “North Field” တိုင်းကို ရှာပြီး ပြောင်းရပါမယ်။ တစ်ခု လွတ်သွားရင် ဒေတာက သူ့ဘာသာ ကွဲလွဲနေပါလိမ့်မယ်။ |
| Insert anomaly | ဇုန် အသစ် S “Pond Side” ထဲက 25 m² စိုက်ကွက် အသစ် Plot 9 ကို တစ်ယောက်ယောက် မငှားမချင်း မှတ်တမ်းတင်လို့ မရပါဘူး: row တစ်ကြောင်းစီက စိုက်ပျိုးသူ တစ်ယောက်ရဲ့ စာရင်းသွင်းမှု ဖြစ်တာကြောင့် ထည့်စရာ row မရှိလို့ပါ။ |
| Delete anomaly | Senior အဖွဲ့ဝင်က Ruth တစ်ယောက်တည်းပါ။ သူ ထွက်သွားလို့ သူ့ စာရင်းသွင်းမှုကို ဖျက်လိုက်ရင် Senior အဖွဲ့ဝင်တွေက တာဝန် 6 နာရီ လုပ်ရတယ်ဆိုတဲ့ အချက်ပါ ဥယျာဉ်ရဲ့ ဒေတာထဲကနေ ပျောက်သွားပါတယ်၊ ဘာလို့လဲဆိုတော့ အဲဒါကို မှတ်ထားတဲ့ တခြား row မရှိလို့ပါ။ |
Normalisation က table ကြီးကို အကြောင်းအရာ တစ်ခုစီအတွက် table အသေးလေးတွေအဖြစ် ခွဲပြီး ဒီပြဿနာတွေကို ဖယ်ရှားပေးပါတယ်။ ဥယျာဉ်အတွက် ဒီလို ခွဲလိုက်တာက:
- အချက် တစ်ခုချင်းစီကို တစ်ကြိမ်ပဲ သိမ်းပါတယ်။ ဇုန် N ရဲ့ နာမည်က row တစ်ကြောင်းတည်းမှာ ရှိတာကြောင့် ဇုန်ကို နာမည်ပြောင်းတာက ပြင်ဆင်မှု တစ်ခုတည်းပါ။ မကိုက်ညီဘဲ ကျန်နေမယ့် ဒုတိယ မိတ္တူ မရှိပါဘူး။
- အချက်တွေကို သီးခြားစီ ထည့်နိုင်၊ ဖယ်နိုင်ပါတယ်။ Plot 9 နဲ့ ဇုန် S ကို စိုက်ကွက်ကို ဘယ်သူမှ မငှားခင်ကတည်းက မှတ်တမ်းတင်ထားနိုင်ပြီး Ruth ရဲ့ ငှားရမ်းမှုကို ဖျက်လိုက်လည်း Senior တာဝန် နာရီတွေ ဆက်ရှိနေပါတယ်။
- DBMS (database ကို စီမံတဲ့ software) က table တွေကြားက ချိတ်ဆက်မှုတွေကို စစ်ပေးနိုင်ပါတယ်။ Foreign key (တခြား table ရဲ့ primary key ကို ညွှန်းတဲ့ column) တွေ ထားထားရင် မရှိတဲ့ စိုက်ကွက်အတွက် ငှားရမ်းမှုကို database က လက်မခံပါဘူး။
- နေရာ သက်သာပါတယ်၊ ဘာလို့လဲဆိုတော့ နာမည်တွေ၊ အရွယ်အစားတွေနဲ့ တာဝန် နာရီတွေကို row တိုင်းမှာ ထပ်ရေးစရာ မလိုတော့လို့ပါ။
ပေးရတဲ့ ကုန်ကျစရိတ်က ဒေတာ ဖတ်တဲ့ဘက်မှာ ရှိပါတယ်: table အများကြီးမှာ ပြန့်နေတဲ့ ဒေတာကို တစ်စုတည်းအဖြစ် ဖတ်ဖို့ join (table တွေကို ပြန်ဆက်ပေါင်းခြင်း) လုပ်ရပါတယ်။ ဒါကြောင့် စနစ် တချို့က denormalise လုပ်ဖို့ ရွေးကြပါတယ် (Denormalisation ကို အကဲဖြတ်ခြင်း ကို ကြည့်ပါ)။
Functional, Partial-Key, and Transitive Dependencies (မှီခိုမှု သုံးမျိုး)
Normalisation ကို column တစ်ခုရဲ့ တန်ဖိုးက နောက် column တစ်ခုရဲ့ တန်ဖိုးပေါ် ဘယ်လို မှီခိုသလဲ ဆိုတာနဲ့ သတ်မှတ်ပါတယ်။ 1NF -> 2NF -> 3NF အတွက် နာမည်ပေးထားတဲ့ dependency သုံးမျိုး အရေးကြီးပါတယ်:
Functional dependency (FD) (column တစ်ခုက နောက်တစ်ခုကို ဆုံးဖြတ်ခြင်း)။ A ရဲ့ တန်ဖိုး တစ်ခုချင်းစီက B ရဲ့ တန်ဖိုး တစ်ခုတည်းနဲ့ အမြဲ ကိုက်ညီနေရင် column B က column A ပေါ် functionally depend ဖြစ်တယ်လို့ ဆိုပါတယ် (A -> B လို့ ရေးပါတယ်)။ ဥပမာ: ZoneCode -> ZoneName။ စည်းမျဉ်း 2 အရ ဇုန် code တစ်ခုစီမှာ နာမည် တစ်ခုတည်း ရှိတာကြောင့် code ကို သိရင် နာမည်ကို သိပါတယ်။ Dependency တစ်ခုဟာ ဒီလို စည်းမျဉ်း တစ်ခုကနေ လာရပါမယ်၊ နမူနာ row တွေမှာ မြင်ရတာ တစ်ခုတည်းကနေ မဟုတ်ရပါဘူး။ Table တစ်ခု 3NF ဖြစ်သွားရင် non-key column (key ထဲမှာ မပါတဲ့ column) တိုင်းက primary key (row တစ်ခုချင်းကို ခွဲခြားပေးတဲ့ key) တစ်ခုလုံးပေါ် တိုက်ရိုက် မှီခိုပါတယ်: key ရဲ့ အပိုင်း တစ်ခုပေါ်ပဲ မှီခိုတာ မဟုတ်သလို တခြား non-key column ကနေတစ်ဆင့် မှီခိုတာလည်း မဟုတ်ပါဘူး။ အောက်က dependency နှစ်မျိုးက ဒီအတိုင်း မဖြစ်ဘဲ မှားသွားတဲ့ နည်း နှစ်မျိုးပါ။
Partial-key dependency။ Column တစ်ခုက key တစ်ခုလုံးပေါ် မဟုတ်ဘဲ column နှစ်ခု ဒါမှမဟုတ် ပိုများတဲ့ column တွေနဲ့ ဖွဲ့ထားတဲ့ key ရဲ့ အပိုင်း တစ်ခုပေါ်မှာပဲ မှီခိုတာပါ။ အဲဒီ key က များသောအားဖြင့် composite primary key (column အများ ပေါင်းထားတဲ့ primary key) ပါ။ ဒါက 2NF ကို ချိုးဖောက်တာပါ။ ဥပမာ: composite key (PlotID, SeasonYear) ပါတဲ့ table မှာ SizeM2 က PlotID ပေါ်မှာပဲ မှီခိုပါတယ်၊ ဘာလို့လဲဆိုတော့ စိုက်ကွက် တစ်ကွက်ကို ဘယ်ရာသီမှာ ငှားငှား အရွယ်အစား အတူတူပဲ ဖြစ်လို့ပါ။ ဒါက partial-key dependency ဖြစ်ပြီး SizeM2 က PlotID ကို key အပြည့်အစုံ အဖြစ် ထားတဲ့ သီးခြား PLOT table ထဲမှာ ရှိသင့်ပါတယ်။
Transitive dependency။ Non-key column တစ်ခုက primary key ပေါ် တိုက်ရိုက် မဟုတ်ဘဲ တခြား non-key column တစ်ခုပေါ် မှီခိုတာပါ။ ဒါက 3NF ကို ချိုးဖောက်တာပါ။ ဥပမာ: primary key PlotID နဲ့ column ZoneCode, ZoneName ပါတဲ့ table မှာ ZoneName က PlotID ပေါ် တိုက်ရိုက် မဟုတ်ဘဲ ZoneCode ပေါ် မှီခိုပါတယ်။ ကွင်းဆက်က PlotID -> ZoneCode -> ZoneName ဖြစ်ပြီး ZoneName က ZoneCode ကို primary key အဖြစ် ထားတဲ့ သီးခြား ZONE table ထဲမှာ ရှိသင့်ပါတယ်။
(လက်ရှိ syllabus (IB သင်ရိုး) မှာ multi-valued dependency တွေကိုလည်း ဖော်ပြထားပါတယ်: key တစ်ခုတည်းနဲ့ ဆိုင်ပြီး တစ်ခုနဲ့ တစ်ခု မသက်ဆိုင်တဲ့ အချက် စာရင်း နှစ်ခုပါ၊ ဥပမာ ဆရာ တစ်ယောက် တီးတဲ့ တူရိယာတွေနဲ့ အဲဒီ ဆရာ ပြောတဲ့ ဘာသာစကားတွေ လိုမျိုးပါ။ သူတို့ကို ဖယ်ရှားပေးတဲ့ normal form ဖြစ်တဲ့ 4NF က syllabus ထက် ကျော်လွန်ပါတယ်၊ ဒါပေမယ့် multi-valued cell တွေ ဆိုတဲ့ လက္ခဏာ ကိုတော့ 1NF က ပြင်ပေးပါတယ်။)
First Normal Form (1NF၊ ပထမ normal form)
Table တစ်ခုဟာ အောက်ပါ အချက်တွေ ပြည့်မီရင် 1NF ဖြစ်ပါတယ်:
- Cell တိုင်းမှာ atomic တန်ဖိုး တစ်ခုတည်းပဲ ရှိရပါမယ်။ Comma နဲ့ ခြားထားတဲ့ စာရင်းတွေ၊ nested record (record ထဲမှာ ထပ်ပါတဲ့ record) တွေ၊ JSON blob (JSON ပုံစံနဲ့ ရေးထားတဲ့ ဒေတာ အစုအဝေး) တွေ မပါရပါဘူး။
- ထပ်ခါထပ်ခါ ပါနေတဲ့ column အုပ်စု (repeating group) မရှိရပါဘူး။ Column တွေကို
Item1,Item2,Item3လို့ နာမည်ပေးနေမိရင် အဲဒါက သီးခြား table တစ်ခု ဖြစ်သင့်တဲ့ repeating group ပါ။ - Row တိုင်းကို တစ်ခုချင်း ခွဲခြားသိနိုင်ရပါမယ်။ သဘာဝအတိုင်း primary key မရှိရင် တစ်ခု ထည့်ပေးပါ။
- Column နာမည်တွေ မတူရပါဘူး။ Column နှစ်ခုမှာ နာမည် တူလို့ မရပါဘူး။
ဥယျာဉ်ရဲ့ စာရင်းသွင်း စာရွက်မှာ 1NF ကို သုံးရင် အောက်ပါအတိုင်း လုပ်ရပါတယ်:
- ရာသီ တစ်ခုစီမှာ ငှားတဲ့ စိုက်ကွက် တစ်ကွက်စီ ကိုယ်ပိုင် row ရအောင်
PlotsRentedစာရင်းကို ခွဲပါတယ်။ ပြီးရင် item တစ်ခုချင်းစီကို column လေးခု ခွဲပါတယ်:PlotID,SizeM2,ZoneCodeနဲ့ZoneName။ - စည်းမျဉ်းတွေကို ကြည့်ပြီး primary key ကို ရွေးပါတယ်။ စာရွက်ရဲ့ မူလ key ဖြစ်တဲ့
(SeasonYear, GardenerID)က အလုပ် မဖြစ်တော့ပါဘူး: Ivy က 2025 မှာ စိုက်ကွက် နှစ်ကွက် ငှားခဲ့လို့ အဲဒီ တန်ဖိုး တစ်တွဲက အခု row နှစ်ကြောင်းမှာ ပေါ်နေပါတယ်။ စည်းမျဉ်း 3 အရ ရာသီ တစ်ခုမှာ စိုက်ကွက် တစ်ကွက်ကို စိုက်ပျိုးသူ အများဆုံး တစ်ယောက်ပဲ ငှားနိုင်တာကြောင့်(PlotID, SeasonYear)က row တိုင်းမှာ မထပ်ပါဘူး။ ဒါက စည်းမျဉ်းတွေက အာမခံပေးတဲ့ အငယ်ဆုံး key ဖြစ်လို့ composite primary key အဖြစ် သတ်မှတ်လိုက်ပါတယ်။
RENTAL (1NF) composite primary key: (PlotID, SeasonYear)
| PlotID | SeasonYear | SizeM2 | ZoneCode | ZoneName | GardenerID | GardenerName | MemberType | DutyHours |
|---|---|---|---|---|---|---|---|---|
| 3 | 2025 | 40 | N | North Field | G11 | Ivy Chen | Full | 10 |
| 3 | 2026 | 40 | N | North Field | G11 | Ivy Chen | Full | 10 |
| 4 | 2025 | 40 | N | North Field | G11 | Ivy Chen | Full | 10 |
| 4 | 2026 | 40 | N | North Field | G12 | Tomás Silva | Junior | 4 |
| 7 | 2025 | 60 | E | East Bank | G15 | Ruth Okoro | Senior | 6 |
| 7 | 2026 | 60 | E | East Bank | G12 | Tomás Silva | Junior | 4 |
ဒီ table က 1NF ဖြစ်ပါတယ်: တန်ဖိုးတွေ atomic ဖြစ်တယ်၊ repeating group မရှိဘူး၊ row တိုင်းကို (PlotID, SeasonYear) နဲ့ ခွဲခြားသိနိုင်တယ်။ အခု ထပ်နေတာတွေကို လွယ်လွယ် မြင်ရပါပြီ: စိုက်ကွက် တစ်ကွက်စီရဲ့ အရွယ်အစားနဲ့ ဇုန်က သူ့ row နှစ်ကြောင်းလုံးမှာ ပေါ်နေပြီး Ivy ရဲ့ အချက်အလက်တွေက သုံးကြိမ် ပေါ်နေပါတယ်။
Second Normal Form (2NF၊ ဒုတိယ normal form)
Table တစ်ခုဟာ အောက်ပါ အချက်တွေ ပြည့်မီရင် 2NF ဖြစ်ပါတယ်:
- 1NF ဖြစ်ပြီးသား ဖြစ်ရပါမယ်။
- Non-key column တိုင်းက primary key ရဲ့ အပိုင်း တစ်ခုပေါ်ပဲ မဟုတ်ဘဲ primary key တစ်ခုလုံး ပေါ် မှီခိုရပါမယ်။ Row ကို ခွဲခြားသိစေနိုင်တဲ့ တခြား column အုပ်စု မှန်သမျှအတွက်လည်း ဒီအတိုင်းပါပဲ။
Partial-key dependency ဖြစ်ဖို့ column နှစ်ခု ဒါမှမဟုတ် ပိုများတဲ့ column တွေနဲ့ ဖွဲ့ထားတဲ့ key လိုပါတယ်။ Table ရဲ့ primary key က column တစ်ခုတည်း ဖြစ်ပြီး row ကို ခွဲခြားသိစေနိုင်တဲ့ တခြား column ဒါမှမဟုတ် column အုပ်စု မရှိရင် “တစ်စိတ်တစ်ပိုင်း” မှီခိုစရာ မရှိပါဘူး။ ဒါကြောင့် ဒီလို 1NF table က အလိုအလျောက် 2NF ဖြစ်ပါတယ်။ ID column တစ်ခု ထည့်လိုက်ရုံနဲ့ partial-key dependency မပျောက်ပါဘူး: RENTAL(RowID, PlotID, SeasonYear, SizeM2) မှာ (PlotID, SeasonYear) တွဲက row တစ်ခုချင်းကို ခွဲခြားသိစေဆဲ ဖြစ်ပြီး SizeM2 ကလည်း PlotID တစ်ခုတည်းပေါ် မှီခိုနေဆဲပါ။ ဒါကြောင့် ဒီ table က 2NF မဖြစ်ပါဘူး။
Composite key (PlotID, SeasonYear) ပါတဲ့ အပေါ်က 1NF RENTAL table ကို ကြည့်ပြီး key ရဲ့ အပိုင်း တစ်ခုချင်းစီကို အလှည့်ကျ စစ်ကြည့်ပါ:
PlotIDတစ်ခုတည်းပေါ် မှီခိုတာ:SizeM2နဲ့ZoneCode(စည်းမျဉ်း 1)၊ ပြီးတော့ZoneCodeကနေတစ်ဆင့်ZoneName(စည်းမျဉ်း 2)။ ဒါတွေက partial-key dependency တွေပါ။SeasonYearတစ်ခုတည်းပေါ် မှီခိုတာ: ဘာမှ မရှိပါဘူး။ စည်းမျဉ်းတွေမှာ ရာသီ တစ်ခုအတွက် သီးသန့် အချက် တစ်ခုမှ မသတ်မှတ်ထားပါဘူး။- Key တစ်ခုလုံးပေါ် မှီခိုတာ:
GardenerID။ Plot 4 ကို ဘယ်သူ ငှားသလဲ ဆိုတာက ရာသီပေါ် မူတည်ပါတယ်: 2025 မှာ Ivy၊ 2026 မှာ Tomás (စည်းမျဉ်း 3)။GardenerName,MemberTypeနဲ့DutyHoursကGardenerIDကနေ ဆင်းသက်လာတာကြောင့် အခုအတွက်တော့ သူနဲ့အတူ ထားခဲ့ပါတယ်၊ 3NF မှာ သူတို့ကို ကိုင်တွယ်ပါမယ်။
အဆိုပြုချက် နှစ်ခုကို စစ်ဆေးခြင်း။ ကော်မတီဝင် နှစ်ယောက်က မတူတဲ့ 2NF design နှစ်ခုကို အကြံပြုပါတယ်:
- အဆိုပြုချက် A:
PLOT(PlotID, SizeM2, ZoneCode, ZoneName, GardenerID, GardenerName, MemberType, DutyHours)နဲ့RENTAL(PlotID, SeasonYear) - အဆိုပြုချက် B:
PLOT(PlotID, SizeM2, ZoneCode, ZoneName)နဲ့RENTAL(PlotID, SeasonYear, GardenerID, GardenerName, MemberType, DutyHours)
တစ်ခုချင်းစီကို စည်းမျဉ်းတွေနဲ့ တိုက်စစ်ကြည့်ပါ။ အဆိုပြုချက် A က စိုက်ကွက် တစ်ကွက်ကို စိုက်ပျိုးသူ တစ်ယောက်တည်းနဲ့ အမြဲတမ်း တွဲထားတာကြောင့် plot 4 ကို 2025 မှာ Ivy ငှားပြီး 2026 မှာ Tomás ငှားခဲ့တယ်ဆိုတာကို မှတ်တမ်းတင်လို့ မရပါဘူး: စည်းမျဉ်း 3 ကို ချိုးဖောက်ပါတယ်။ အဆိုပြုချက် B က PlotID တစ်ခုတည်းပေါ် မှီခိုတဲ့ column တွေကိုပဲ ရွှေ့ပြီး စိုက်ပျိုးသူကို ရာသီနဲ့ တွဲထားတာကြောင့် အဆိုပြုချက် B က 2NF design ဖြစ်ပါတယ်:
PLOT (2NF) PK (primary key): PlotID
| PlotID | SizeM2 | ZoneCode | ZoneName |
|---|---|---|---|
| 3 | 40 | N | North Field |
| 4 | 40 | N | North Field |
| 7 | 60 | E | East Bank |
RENTAL (2NF) composite PK: (PlotID, SeasonYear); FK (foreign key): PlotID -> PLOT
| PlotID | SeasonYear | GardenerID | GardenerName | MemberType | DutyHours |
|---|---|---|---|---|---|
| 3 | 2025 | G11 | Ivy Chen | Full | 10 |
| 3 | 2026 | G11 | Ivy Chen | Full | 10 |
| 4 | 2025 | G11 | Ivy Chen | Full | 10 |
| 4 | 2026 | G12 | Tomás Silva | Junior | 4 |
| 7 | 2025 | G15 | Ruth Okoro | Senior | 6 |
| 7 | 2026 | G12 | Tomás Silva | Junior | 4 |
အခု non-key column တိုင်းက သူ့ table ရဲ့ key တစ်ခုလုံးပေါ် မှီခိုပါပြီ။ Partial-key dependency တွေ မရှိတော့ပေမယ့် table နှစ်ခုလုံးမှာ အချက်တွေ ထပ်နေဆဲပါ။
Third Normal Form (3NF၊ တတိယ normal form)
Table တစ်ခုဟာ အောက်ပါ အချက်တွေ ပြည့်မီရင် 3NF ဖြစ်ပါတယ်:
- 2NF ဖြစ်ပြီးသား ဖြစ်ရပါမယ်။
- Non-key column တစ်ခုမှ တခြား non-key column ပေါ် မမှီခိုရပါဘူး (transitive dependency မရှိရပါဘူး)။
2NF table နှစ်ခုလုံးမှာ transitive dependency တွေ ရှိနေပါတယ်။
PLOT ထဲမှာ: PlotID -> ZoneCode -> ZoneName။ ဇုန်ရဲ့ နာမည်က ဇုန်နဲ့ ဆိုင်တဲ့ အချက် ဖြစ်တာကြောင့် (စည်းမျဉ်း 2) ZoneCode ကို key အဖြစ် ထားတဲ့ ZONE table ထဲ ရွှေ့ပါတယ်။ PLOT က ZoneCode ကို foreign key အဖြစ် ဆက်ထားပါတယ်။
RENTAL ထဲမှာ: ပိုရှည်တဲ့ ကွင်းဆက် (PlotID, SeasonYear) -> GardenerID -> MemberType -> DutyHours ရှိပြီး GardenerName ကလည်း GardenerID ပေါ် မှီခိုပါတယ်။
GardenerNameနဲ့MemberTypeက စိုက်ပျိုးသူနဲ့ ဆိုင်တဲ့ အချက်တွေ ဖြစ်လို့ (စည်းမျဉ်း 4)GardenerIDကို key အဖြစ် ထားတဲ့GARDENERtable ထဲ ရွှေ့ပါတယ်။ စိုက်ပျိုးသူ နှစ်ယောက်မှာ နာမည် တူနိုင်တာကြောင့် နာမည်ကို key အဖြစ် သုံးလို့ မရပါဘူး။- အဲဒီ
GARDENERtable ထဲမှာDutyHoursကျန်နေဦးမှာပါ။DutyHoursက တခြား non-key column ဖြစ်တဲ့MemberTypeပေါ် မှီခိုပါတယ် (စည်းမျဉ်း 5)။ ဒါကြောင့်DutyHoursကို နောက်တစ်ဆင့် ထပ်ရွှေ့ပြီးMemberTypeကို key အဖြစ် ထားတဲ့MEMBER_TYPEtable ထဲ ထည့်ပါတယ်။ RENTALမှာGardenerIDကိုပဲ foreign key အဖြစ် ချန်ထားပါတယ်။
ZONE (3NF) PK: ZoneCode
| ZoneCode | ZoneName |
|---|---|
| N | North Field |
| E | East Bank |
PLOT (3NF) PK: PlotID; FK: ZoneCode -> ZONE
| PlotID | SizeM2 | ZoneCode |
|---|---|---|
| 3 | 40 | N |
| 4 | 40 | N |
| 7 | 60 | E |
MEMBER_TYPE (3NF) PK: MemberType
| MemberType | DutyHours |
|---|---|
| Full | 10 |
| Junior | 4 |
| Senior | 6 |
GARDENER (3NF) PK: GardenerID; FK: MemberType -> MEMBER_TYPE
| GardenerID | GardenerName | MemberType |
|---|---|---|
| G11 | Ivy Chen | Full |
| G12 | Tomás Silva | Junior |
| G15 | Ruth Okoro | Senior |
RENTAL (3NF) composite PK: (PlotID, SeasonYear); FKs: PlotID -> PLOT, GardenerID -> GARDENER
| PlotID | SeasonYear | GardenerID |
|---|---|---|
| 3 | 2025 | G11 |
| 3 | 2026 | G11 |
| 4 | 2025 | G11 |
| 4 | 2026 | G12 |
| 7 | 2025 | G15 |
| 7 | 2026 | G12 |
Table တစ်ခုက table ငါးခု ဖြစ်သွားပါပြီ။ အခု table တိုင်းက non-key column (key ထဲမှာ မပါတဲ့ column) တိုင်းဟာ the key, the whole key, and nothing but the key (key ပေါ်၊ key တစ်ခုလုံးပေါ်၊ key ပေါ်မှာပဲ) မှီခိုပါတယ်။ ဒါက 3NF ကို ဖော်ပြတဲ့ လူသိများတဲ့ စကားစုပါ။
“Key, Whole Key, Nothing But the Key” မှတ်စရာ စကားစု
Normal form သုံးမျိုးကို မှတ်မိဖို့ လူအများ ကိုးကားလေ့ရှိတဲ့ နည်း:
- 1NF: column တိုင်းက the key (key) ပေါ် မှီခိုပါတယ် (cell တစ်ခုမှာ တန်ဖိုး တစ်ခုတည်း၊ row တိုင်းကို တစ်ခုချင်း ခွဲခြားသိနိုင်တယ်)။
- 2NF: column တိုင်းက the whole key (key တစ်ခုလုံး) ပေါ် မှီခိုပါတယ် (composite key တွေမှာ partial-key dependency မရှိဘူး)။
- 3NF: column တိုင်းက nothing but the key ပေါ် မှီခိုပါတယ်၊ ဆိုလိုတာက key ကလွဲပြီး တခြား ဘာပေါ်မှ မမှီခိုပါဘူး (တခြား non-key column တွေကနေတစ်ဆင့် ဖြစ်တဲ့ transitive dependency မရှိဘူး)။
Update, Insert, and Delete Anomalies (ပြင်တဲ့အခါ၊ ထည့်တဲ့အခါ၊ ဖျက်တဲ့အခါ ဖြစ်တဲ့ ပြဿနာများ)
Normalisation ရှိရတဲ့ အဓိက ရည်ရွယ်ချက်က anomaly သုံးမျိုးကို ဖယ်ရှားဖို့ပါ။ တစ်မျိုးချင်းစီက ဥယျာဉ်ရဲ့ table တစ်ခုတည်းမှာ ဖြစ်ပေမယ့် 3NF schema (database ဖွဲ့စည်းပုံ ဖော်ပြချက်) မှာ မဖြစ်တဲ့ လက်တွေ့ ချို့ယွင်းချက်တွေပါ:
| Anomaly | Normalise မလုပ်ရသေးတဲ့ ပုံစံ | 3NF ပုံစံ |
|---|---|---|
| Update | ဇုန် N ကို နာမည်ပြောင်းရင် ရာသီတိုင်းမှာ ဇုန်ထဲက စိုက်ကွက်တိုင်းအတွက် “North Field” ကို ပြောင်းရပါမယ်။ တစ်ခု လွတ်သွားရင် ဒေတာက သူ့ဘာသာ ကွဲလွဲနေပါလိမ့်မယ်။ | ZONE.ZoneName ကို တစ်ကြိမ်ပဲ ပြောင်းရပါတယ်။ ဇုန် N ထဲက စိုက်ကွက်တိုင်းက foreign key ချိတ်ဆက်မှုကနေတစ်ဆင့် နာမည် အသစ်ကို ပြပါတယ်။ |
| Insert | တစ်ယောက်ယောက် မငှားမချင်း စိုက်ကွက် အသစ်ကို မှတ်တမ်းတင်လို့ မရပါဘူး၊ ထည့်စရာ row မရှိလို့ပါ။ | PLOT ထဲကို row တစ်ကြောင်း ထည့်ပါ (ဇုန် အသစ် ဆိုရင် ZONE ထဲကိုလည်း ထည့်ပါ)။ ငှားရမ်းမှု မလိုပါဘူး။ |
| Delete | တစ်ယောက်တည်းသော Senior အဖွဲ့ဝင်ရဲ့ တစ်ခုတည်းသော ငှားရမ်းမှုကို ဖျက်လိုက်ရင် Senior အဖွဲ့ဝင်တွေက တာဝန် 6 နာရီ လုပ်ရတယ်ဆိုတဲ့ အချက်ပါ ပျက်သွားပါတယ်။ | RENTAL ထဲက row ကို ဖျက်ပါ။ GARDENER နဲ့ MEMBER_TYPE row တွေ ကျန်နေပါတယ်။ |
မေးခွန်းက “Outline why the table is not in 3NF” ဒါမှမဟုတ် “Explain why this table should be normalised” လို့ မေးရင် redundancy ကြောင့် ဖြစ်လာနိုင်တဲ့ anomaly ကို တိတိကျကျ ဖော်ပြပါ။ (ပထမ မေးခွန်းက table ဘာကြောင့် 3NF မဖြစ်သလဲ Outline (အကျဉ်းချုပ် ဖော်ပြပါ) လုပ်ခိုင်းတာ ဖြစ်ပြီး ဒုတိယ မေးခွန်းက ဒီ table ကို ဘာကြောင့် normalise လုပ်သင့်သလဲ Explain (ရှင်းပြပါ) လုပ်ခိုင်းတာပါ။)
3NF Schema တည်ဆောက်တဲ့ အဆင့်များ
3NF schema တစ်ခုကို တည်ဆောက်ဖို့ ဒီ အဆင့်တွေအတိုင်း လုပ်ပါ:
- Unnormalised table ထဲက attribute (table ရဲ့ column တစ်ခုစီ) အားလုံးကို ရှာဖော်ပါ။
- တန်ဖိုး တိုင်းကို atomic ဖြစ်အောင် လုပ်ပါ: column တစ်ခုမှာ စာရင်း ပါနေရင် စာရင်းထဲက element (အစုထဲက အချက်) တစ်ခုချင်းစီကို ကိုယ်ပိုင် row ထဲ ခွဲထည့်ပါ။
- Primary key ကို ထည့်ပါ ဒါမှမဟုတ် ရှာဖော်ပါ: row တိုင်းမှာ မထပ်တဲ့ အငယ်ဆုံး column အစုကို စည်းမျဉ်းတွေကို သုံးပြီး ရှာပါ။ အဲဒါက composite key ဖြစ်လေ့ ရှိပြီး မူလ table ရဲ့ key နဲ့ အမြဲ တူတာ မဟုတ်ပါဘူး (ဥယျာဉ်ရဲ့ စာရင်းသွင်း စာရွက်က ဥပမာ တစ်ခုပါ)။
- Partial-key dependency တွေကို ရှာပါ (column နှစ်ခု ဒါမှမဟုတ် ပိုများတဲ့ column တွေနဲ့ ဖွဲ့ထားတဲ့ key က row ကို ခွဲခြားသိစေနိုင်မှသာ ရှာရပါတယ်၊ အဲဒီ key က များသောအားဖြင့် composite primary key ပါ)။ Key ရဲ့ အပိုင်း တစ်ခုပေါ်ပဲ မှီခိုတဲ့ column တွေကို သူတို့ကိုယ်ပိုင် table ထဲ ရွှေ့ပါ၊ အဲဒီ key အပိုင်းက table အသစ်ရဲ့ primary key ဖြစ်လာပါတယ်။
- Transitive dependency တွေကို ရှာပါ။ တခြား non-key column တစ်ခုပေါ် မှီခိုတဲ့ column မှန်သမျှကို အဲဒီ non-key column ကို key အဖြစ် ထားတဲ့ table အသစ်ထဲ ရွှေ့ပါ။
- Table အသစ်တွေကို ပြန်ချိတ်ပေးမယ့် foreign key တွေကို ထည့်ပါ။
- နောက်ဆုံး ပြန်စစ်ပါ။ Table တစ်ခုချင်းစီကို
TABLE(PK, attr1, attr2, ...)ပုံစံနဲ့ အသံထွက် ဖတ်ကြည့်ပါ။ Attribute တိုင်းက primary key နဲ့ ဆိုင်တဲ့ အချက် ဖြစ်ရပါမယ်၊ တခြား ဘာမှ မဖြစ်ရပါဘူး။
Denormalisation ကို အကဲဖြတ်ခြင်း (A3.2.7)
Normalisation က ပုံမှန် ရွေးချယ်မှုပါ။ ဒါပေမယ့် တစ်ခုခု ပြန်ရဖို့အတွက် redundancy တချို့ကို တမင် ပြန်ထည့်တဲ့ အခြေအနေတွေ ရှိပါတယ်၊ ဒါကို denormalisation လို့ ခေါ်ပါတယ်။ ဒါက A3.2.7 ရဲ့ ခေါင်းစဉ်ပါ။
Denormalisation က တစ်ခါတစ်ရံ တန်တဲ့ အခြေအနေများ:
- Read-heavy workload (ရေးတာထက် ဖတ်တာ အများကြီး ပိုများတဲ့ အလုပ်) များ။ Table ခြောက်ခုကို ပေါင်းတဲ့ JOIN တစ်ခုတည်းကို တစ်မိနစ်မှာ အကြိမ် ထောင်ချီ run နေတဲ့ report dashboard (အချက်အလက်တွေကို စုပြတဲ့ မျက်နှာပြင်) တစ်ခုဟာ join လုပ်ပြီးသား ရလဒ်ကို denormalised table တစ်ခုတည်းအဖြစ် materialise (ကြိုတင် တွက်ပြီး သိမ်း) လုပ်ထားရင် အများကြီး ပိုမြန်နိုင်ပါတယ်။
- ခွဲခြမ်းစိတ်ဖြာရေး / warehouse စနစ်များ။ Data warehouse (ခွဲခြမ်းစိတ်ဖြာဖို့ ယခင် ဒေတာ သိုလှောင်ရုံ) တွေကို (Data Warehouses မှာ လေ့လာနိုင်ပါတယ်) ဒေတာ ရေးတာထက် query (database ထဲက ဒေတာကို ရှာ၊ ပြင်ဖို့ ပေးတဲ့ အမိန့်) လုပ်တာ အများကြီး ပိုများလို့ တမင် denormalise လုပ်ထားပါတယ်။
- Hot path (အကြိမ်အများဆုံး run ရတဲ့ code လမ်းကြောင်း) ပေါ်က ကုန်ကျစရိတ် များတဲ့ join တွေကို ဖယ်ရှားခြင်း။ Latency (တောင်းဆိုမှုနဲ့ တုံ့ပြန်မှုကြား နှောင့်နှေးချိန်) အရေးကြီးတဲ့အခါ customer ရဲ့ လက်ရှိ လိပ်စာကို order row ထဲ ကြိုပေါင်းထည့်ထားတာက disk (ကွန်ပျူတာရဲ့ storage) နေရာကို ပိုသုံးပြီး query မြန်နှုန်းကို ရယူတာပါ။
ဆုံးရှုံးရတာတွေ:
- Update anomaly တွေ ပြန်ဖြစ်လာပါတယ်။ Order တိုင်းမှာ ထပ်ထည့်ထားတဲ့ customer ရဲ့ လက်ရှိ လိပ်စာ မိတ္တူတွေကို တစ်နေရာရာကနေ မှန်နေအောင် ထိန်းပေးရပါတယ်၊ များသောအားဖြင့် trigger (ဒေတာ ပြောင်းတိုင်း အလိုအလျောက် run တဲ့ database code) ဒါမှမဟုတ် application code နဲ့ လုပ်ပါတယ်။
- Storage (ဒေတာ သိမ်းဆည်းရာ) နဲ့ ရေးတဲ့ ကုန်ကျစရိတ် တက်လာပါတယ်။ ထပ်နေတဲ့ column တိုင်းက disk နေရာ ယူပြီး ရေးတာကို နှေးစေပါတယ်။
- ဒေတာ မကိုက်ညီမှု ဖြစ်နိုင်ခြေ။ သေချာ မထိန်းသိမ်းရင် ဒေတာ မိတ္တူ နှစ်ခုက တဖြည်းဖြည်း ကွဲသွားပြီး ဘယ်ဟာ မှန်လဲ မသိတော့ပါဘူး။
ဆက်စပ်တဲ့ အခြေအနေ: မိတ္တူလား၊ ဖြစ်ခဲ့တာရဲ့ မှတ်တမ်းလား။ Denormalise လုပ်တာက လက်ရှိ တန်ဖိုး တစ်ခုရဲ့ မိတ္တူကို ဒုတိယ နေရာ တစ်ခုမှာ ထားတာ ဖြစ်ပြီး ပြောင်းလဲမှု တိုင်းက နေရာ နှစ်ခုလုံးကို ရောက်ရပါတယ်။ ဖြစ်ရပ် တစ်ခု ဖြစ်တဲ့အချိန်မှာ မှတ်ထားတဲ့ တန်ဖိုးကတော့ တခြား အရာပါ။ ပါဆယ် တစ်ခုချင်းစီကို တကယ် ပို့ခဲ့တဲ့ လိပ်စာကို သိမ်းထားတဲ့ ပါဆယ် ကုမ္ပဏီဟာ အဲဒီ ပို့ဆောင်မှုနဲ့ ဆိုင်တဲ့ အချက်ကို မှတ်တမ်းတင်တာပါ: အဲဒီ လိပ်စာက ပါဆယ်ပေါ် မှီခိုပြီး နောက်ပိုင်း customer အိမ်ပြောင်းသွားလည်း မပြောင်းဘဲ ဒီအတိုင်း ရှိနေသင့်ပါတယ်။ ဒါက redundancy မဟုတ်သလို normalisation ကလည်း ဒါကို မဖယ်ရှားပါဘူး။ Customer ရဲ့ လက်ရှိ လိပ်စာကို ပါဆယ် row တိုင်းမှာ ထည့်ထားပြီး customer အိမ်ပြောင်းတိုင်း row အားလုံးကို update လုပ်ရမယ်ဆိုရင်တော့ အဲဒါက မိတ္တူ ဖြစ်ပြီး redundancy ပါ။
ဆုံးဖြတ်ချက်ကို ဘယ်လို အကဲဖြတ်မလဲ:
| မေးခွန်း | ဟုတ်ရင် ဘယ်ဘက်ကို ဦးစားပေးမလဲ… |
|---|---|
| ကုန်ကျစရိတ် များတဲ့ JOIN တစ်ခုတည်းက workload ရဲ့ အများစု ဖြစ်နေသလား။ | Denormalise |
| ဖတ်တာက ရေးတာထက် အများကြီး ပိုများသလား။ | Denormalise |
| ယခင် မှတ်တမ်း တစ်ခုမှာ ဖြစ်ရပ် ဖြစ်ခဲ့တဲ့ အချိန်က တန်ဖိုးအတိုင်း လိုသလား (ပါဆယ် ပို့ခဲ့တဲ့ လိပ်စာ လိုမျိုး)။ | ဖြစ်ရပ်နဲ့အတူ မှတ်တမ်းတင်ပါ: ဒါက အဲဒီ ဖြစ်ရပ်နဲ့ ဆိုင်တဲ့ အချက် ဖြစ်ပြီး မိတ္တူ မဟုတ်ပါဘူး |
| အချက် တစ်ခုစီအတွက် ရှင်းပြရလွယ်တဲ့ canonical version (တရားဝင် မူရင်း တစ်ခုတည်း) လိုသလား။ | Normalise |
| ရေးတာ မကြာခဏ ဖြစ်ပြီး update တွေ atomic (အကုန်ဖြစ် ဒါမှမဟုတ် ဘာမှမဖြစ်) ဖြစ်ရမလား။ | Normalise |
| Storage နဲ့ disk ရေးတဲ့ ကုန်ကျစရိတ်တွေ တင်းကျပ်နေပြီလား။ | Normalise |
Command term (မေးခွန်းက ဘာလုပ်ခိုင်းလဲ ပြတဲ့ IB ရဲ့ သတ်မှတ် စကားလုံး) Evaluate (အားသာချက်နဲ့ အားနည်းချက်တွေကို ချိန်ဆပြီး အကဲဖြတ်ပါ) က နှစ်ဘက်လုံးကို ချိန်ဆပြီး အကြောင်းပြချက် ခိုင်လုံတဲ့ နိဂုံး ချခိုင်းတာပါ။ အဖြေ ကောင်းတစ်ခုမှာ တိကျတဲ့ အခြေအနေ တစ်ခုကို ဖော်ပြတယ်၊ trade-off (တစ်ခု ရဖို့ တစ်ခု အလျှော့ပေးရတာ) ကို ဖော်ထုတ်တယ်၊ ပြီးတော့ ရွေးချယ်မှု တစ်ခုကို အကြောင်းပြချက်နဲ့ အကြံပြုပါတယ်။
ဖြေရှင်းပြထားတဲ့ ဥပမာများ
ဥပမာ 1: ရပ်ကွက် ဥယျာဉ်ကို 3NF အထိ normalise လုပ်ခြင်း
ဒါကို အပေါ်မှာ အဆင့်ဆင့် လုပ်ပြခဲ့ပြီးပါပြီ။ နောက်ဆုံး ရတဲ့ 3NF schema က:
ZONE(ZoneCode, ZoneName)
PLOT(PlotID, SizeM2, ZoneCode*) * = foreign key
MEMBER_TYPE(MemberType, DutyHours)
GARDENER(GardenerID, GardenerName, MemberType*)
RENTAL(PlotID*, SeasonYear, GardenerID*) composite PK (PlotID, SeasonYear)
Block ထဲက * = foreign key က * ပါတဲ့ column တွေဟာ foreign key ဖြစ်တယ်လို့ ဆိုလိုပြီး composite PK (PlotID, SeasonYear) က RENTAL ရဲ့ primary key ဟာ column နှစ်ခု ပေါင်းထားတဲ့ key ဖြစ်တယ်လို့ ဆိုလိုပါတယ်။
မှတ်ချက်များ:
- စည်းမျဉ်းတွေ ဖော်ပြတဲ့ အရာ အမျိုးအစား တစ်ခုစီအတွက် table တစ်ခုစီ ရှိပါတယ် (ဇုန်၊ စိုက်ကွက်၊ အဖွဲ့ဝင် အမျိုးအစားနဲ့ စိုက်ပျိုးသူ)၊ ပြီးတော့ စိုက်ကွက်၊ ရာသီနဲ့ စိုက်ပျိုးသူတွေကို ချိတ်ပေးတဲ့ ငှားရမ်းမှုတွေအတွက် table တစ်ခု ရှိပါတယ်။
SeasonYearကRENTALရဲ့ key ထဲမှာ ပါပေမယ့် ကိုယ်ပိုင် table မရှိပါဘူး၊ ဘာလို့လဲဆိုတော့ စည်းမျဉ်းတွေမှာ ရာသီနဲ့ ဆိုင်တဲ့ ဘာအချက်မှ မမှတ်ထားလို့ပါ။ နောက်ပိုင်း ဥယျာဉ်က ဥပမာ ရာသီ တစ်ခုစီ စဖွင့်တဲ့ ရက်စွဲကို မှတ်မယ်ဆိုရင်SEASON(SeasonYear, OpeningDate)table က အဲဒါကို သိမ်းပြီးRENTAL.SeasonYearက foreign key ဖြစ်လာပါမယ်။RENTALရဲ့ တစ်ခုတည်းသော non-key column ဖြစ်တဲ့GardenerIDကိုယ်တိုင်က foreign key ပါ: key တစ်ခုလုံးပေါ် မှီခိုတဲ့ အချက်က အဲဒီ ရာသီမှာ စိုက်ကွက်ကို ဘယ်သူ ငှားခဲ့သလဲ ဆိုတာပါ။- Design ထဲက dependency တိုင်းက စည်းမျဉ်း ငါးခုထဲက တစ်ခုခုကနေ လာပါတယ်။ နမူနာ row တွေမှာ 40 m² စိုက်ကွက် တိုင်းက တိုက်ဆိုင်စွာ ဇုန် N ထဲမှာ ရှိနေပေမယ့် စိုက်ကွက်ရဲ့ အရွယ်အစားကို ဇုန်နဲ့ ချိတ်တဲ့ စည်းမျဉ်း မရှိပါဘူး။ ဒါကြောင့်
SizeM2 -> ZoneCodeက dependency မဟုတ်ပါဘူး၊ design ကလည်း ဒါကို မသုံးပါဘူး။
ဥပမာ 2: အားကစား ကလပ် table ထဲက dependency တွေကို ရှာခြင်း
Harbour Run အားကစား ကလပ်က ကြိုတင် စာရင်းသွင်းမှု (booking) တွေကို spreadsheet (ဇယားကွက် စာရင်း software) တစ်ခုတည်းနဲ့ စမှတ်ပါတယ်။ ကလပ်ရဲ့ စည်းမျဉ်းတွေ:
- Booking (
BookingID) တစ်ခုကို အဖွဲ့ဝင် တစ်ယောက်က လေ့ကျင့်ရေး အတန်း (class) တစ်ခုအတွက် လုပ်ပါတယ်။ အဖွဲ့ဝင် တစ်ယောက်က အတန်း တစ်ခုတည်းကို တစ်ကြိမ်ထက် ပိုပြီး book လုပ်နိုင်ပါတယ်၊ ဥပမာ မတူတဲ့ အပတ်တွေမှာပါ။ - အဖွဲ့ဝင် တစ်ယောက်ချင်းစီမှာ ID (
MemberID) တစ်ခုနဲ့ နာမည် တစ်ခုတည်း ရှိပါတယ်။ - အတန်း တစ်ခုချင်းစီမှာ ID (
ClassID) တစ်ခု၊ ခေါင်းစဉ် တစ်ခုနဲ့ နည်းပြ တစ်ယောက်တည်း ရှိပါတယ်။
BOOKING (စတင်တဲ့ table)
| BookingID | MemberID | MemberName | ClassID | ClassTitle | CoachName |
|---|---|---|---|---|---|
| B9001 | 1001 | Aroha K. | C401 | Sunrise 5k | Lila O. |
| B9002 | 1002 | Marlon T. | C401 | Sunrise 5k | Lila O. |
| B9003 | 1002 | Marlon T. | C402 | Track Sprints | Lila O. |
| B9004 | 1004 | Priya N. | C403 | Hill Repeats | Daniel P. |
Primary key: BookingID က booking တစ်ခုချင်းကို ခွဲခြားသိစေပြီး ဒါက တစ်ခုတည်းသော နည်းပါ: အဖွဲ့ဝင် တစ်ယောက်က အတန်း တစ်ခုတည်းကို တစ်ကြိမ်ထက် ပို book လုပ်နိုင်တာကြောင့် (MemberID, ClassID) က booking ကို ခွဲခြားမပေးနိုင်ပါဘူး။ Cell တိုင်းမှာ တန်ဖိုး တစ်ခုစီပဲ ရှိလို့ table က 1NF ဖြစ်ပြီးသားပါ။ သူ့ရဲ့ တစ်ခုတည်းသော key က column တစ်ခုတည်း ဖြစ်လို့ 2NF လည်း ဖြစ်ပါတယ် (partial-key dependency ဖြစ်နိုင်ခြေ မရှိပါဘူး)။ ကျန်နေတဲ့ မေးခွန်းက table က 3NF ဖြစ်မဖြစ် ဆိုတာပါ။
Transitive dependency များ:
MemberID -> MemberName: အဖွဲ့ဝင် တစ်ယောက်မှာ နာမည် တစ်ခုပဲ ရှိလို့MemberNameကBookingIDပေါ် တိုက်ရိုက် မဟုတ်ဘဲMemberIDပေါ် မှီခိုပါတယ်။ 3NF ကို ချိုးဖောက်ပါတယ်။ClassID -> ClassTitleနဲ့ClassID -> CoachName: အတန်း တစ်ခုမှာ ခေါင်းစဉ် တစ်ခုနဲ့ နည်းပြ တစ်ယောက်ပဲ ရှိလို့ နှစ်ခုလုံးကBookingIDပေါ် မဟုတ်ဘဲClassIDပေါ် မှီခိုပါတယ်။ 3NF ကို ချိုးဖောက်ပါတယ်။
3NF ရောက်ဖို့:
MEMBER(MemberID, MemberName)
CLASS(ClassID, ClassTitle, CoachName)
BOOKING(BookingID, MemberID*, ClassID*, BookedOn)
အခု table တိုင်းမှာ non-key column တိုင်းက primary key ပေါ်မှာပဲ မှီခိုပါတယ်။ BookedOn (booking တစ်ခုစီ လုပ်ခဲ့တဲ့ ရက်စွဲ) က ကလပ်က table တွေကို design လုပ်တဲ့အခါ ထည့်တဲ့ column အသစ်ပါ၊ spreadsheet မှာ ဒါကို မမှတ်ခဲ့ပါဘူး။
ဥပမာ 3: ပန်းချီ ပြခန်း တစ်ခုအတွက် 3NF တည်ဆောက်ခြင်း
ပန်းချီ ပြခန်း အသေးလေး တစ်ခုက ဘယ် အနုပညာ လက်ရာ (artwork) တွေကို ဘယ် ပြပွဲ (exhibition) တွေမှာ ပြခဲ့သလဲ၊ ဘယ် အနုပညာရှင်ရဲ့ လက်ရာလဲ၊ ဘယ်ဈေးနဲ့ ပြခဲ့သလဲ ဆိုတာကို မှတ်ထားချင်ပါတယ်။ သူတို့ရဲ့ စတင်တဲ့ table:
GALLERY_LOG (စတင်တဲ့ table)
| ExhibitID | ArtworkID | Title | ArtistID | ArtistName | ArtistCountry | DisplayPrice |
|---|---|---|---|---|---|---|
| EX01 | A1001 | Tide | AR05 | Sebastián Q. | Peru | 1200.00 |
| EX01 | A1002 | Anchor | AR05 | Sebastián Q. | Peru | 850.00 |
| EX01 | A1003 | Mistral | AR12 | Priya N. | India | 2400.00 |
| EX02 | A1001 | Tide | AR05 | Sebastián Q. | Peru | 1350.00 |
အဆင့် 1: Primary key။ လက်ရာ တစ်ခုတည်းက မတူတဲ့ ပြပွဲတွေမှာ မတူတဲ့ ဈေးနဲ့ ပေါ်ပါတယ်။ သဘာဝကျတဲ့ composite PK က (ExhibitID, ArtworkID) ပါ။
အဆင့် 2: Partial-key dependency များ။
TitleကArtworkIDပေါ်မှာပဲ မှီခိုပါတယ်။ArtistIDကArtworkIDပေါ်မှာပဲ မှီခိုပါတယ် (လက်ရာ တစ်ခုစီမှာ အနုပညာရှင် တစ်ယောက်ပဲ ရှိပါတယ်)။ArtistNameကArtistIDပေါ် မှီခိုပြီးArtistIDကArtworkIDပေါ် မှီခိုပါတယ်၊ ကွင်းဆက် တစ်ခုပါ။ArtistCountryကလည်း အဲဒီလိုပဲArtistIDပေါ် မှီခိုပါတယ်။DisplayPriceက key တစ်ခုလုံး ပေါ် မှီခိုပါတယ် (ဈေးနှုန်းက ဒီ ပြပွဲ + ဒီ လက်ရာ အတွက်ပဲ သီးသန့် ဖြစ်ပါတယ်)။
ဒါကြောင့် Title, ArtistID, ArtistName, ArtistCountry တို့မှာ partial-key dependency ရှိပါတယ်။
အဆင့် 3: Transitive dependency များ။ မကြာခင် ဖြစ်လာမယ့် ARTWORK table ထဲမှာ ArtistName နဲ့ ArtistCountry က ArtworkID ပေါ် တိုက်ရိုက် မဟုတ်ဘဲ ArtistID ပေါ် မှီခိုပါတယ်: ကွင်းဆက်က ArtworkID -> ArtistID -> ArtistName, ArtistCountry ပါ။ ဒါကြောင့် ArtistName နဲ့ ArtistCountry ကို ArtistID ကို key အဖြစ် ထားတဲ့ ARTIST table ထဲ ရွှေ့ပါတယ်။ (အနုပညာရှင် နှစ်ယောက် နာမည် တူနိုင်တာကြောင့် အနုပညာရှင်ရဲ့ နာမည်ကို determinant (တခြား column တွေရဲ့ တန်ဖိုးကို ဆုံးဖြတ်ပေးတဲ့ column) အဖြစ် မသုံးပါဘူး။)
အဆင့် 4: 3NF schema။
ARTIST(ArtistID, ArtistName, ArtistCountry)
ARTWORK(ArtworkID, Title, ArtistID*)
EXHIBIT(ExhibitID, ExhibitName, OpenDate, CloseDate)
DISPLAY(ExhibitID*, ArtworkID*, DisplayPrice)
EXHIBIT table က DISPLAY.ExhibitID ညွှန်းစရာ table တစ်ခု ရှိအောင် လုပ်ပေးပါတယ်။ ExhibitName, OpenDate နဲ့ CloseDate က ပြခန်းက table တွေကို design လုပ်တဲ့အခါ ထည့်တဲ့ column အသစ်တွေပါ၊ GALLERY_LOG ထဲမှာ မပါခဲ့ပါဘူး။
ပြည့်စုံတဲ့ အဖြေမှာ table တိုင်းကို သူ့ရဲ့ primary key နဲ့ foreign key တွေနဲ့အတူ ပြရပါတယ်။
Quick Check (အမြန် စစ်ဆေးမေးခွန်း)
Q1. အောက်ပါတွေထဲက ဘယ်ဟာက first normal form (1NF) ရဲ့ လိုအပ်ချက် ဖြစ်သလဲ။
Q2. 1NF ကနေ 2NF ကို ပြောင်းတာက ဘယ်လို dependency မျိုးကို ဖယ်ရှားတာလဲ။
Q3. 2NF ကနေ 3NF ကို ပြောင်းတာက ဘယ်လို dependency မျိုးကို ဖယ်ရှားတာလဲ။
Q4. ရပ်ကွက် ဥယျာဉ်ရဲ့ ငှားရမ်းမှု table ကို normalise မလုပ်ခင်မှာ ဇုန် N ရဲ့ နာမည် "North Field" က row 47 ကြောင်းမှာ ပါနေပါတယ်။ ကော်မတီက ဇုန်ကို နာမည်ပြောင်းတဲ့အခါ အဲဒီ row တွေထဲက တစ်ကြောင်းကို update မလုပ်မိရင် ဖြစ်လာတဲ့ ပြဿနာက ဘယ်လို anomaly မျိုးရဲ့ ဥပမာ ဖြစ်သလဲ။
Q5. Table တစ်ခုက 1NF ဖြစ်ပြီး column တစ်ခုတည်းနဲ့ ဖွဲ့ထားတဲ့ သူ့ primary key က row ကို ခွဲခြားသိနိုင်တဲ့ တစ်ခုတည်းသော နည်း ဖြစ်ပါတယ်။ ဘယ်ဟာ မှန်သလဲ။
Q6. ဘယ်အခြေအနေက database ကို denormalise လုပ်ဖို့ အခိုင်မာဆုံး ထောက်ခံသလဲ။
Spot the Dependency (dependency အမျိုးအစားကို ခွဲခြားခြင်း)
အခြေအနေ တစ်ခုချင်းစီအတွက် ဖော်ပြထားတဲ့ dependency အမျိုးအစားကို ရိုက်ထည့်ပါ။
ဖော်ပြထားတဲ့ column က primary key ပေါ် ဘယ်လို မှီခိုသလဲ ဆုံးဖြတ်ပါ: direct (key တစ်ခုလုံးပေါ် တိုက်ရိုက်)၊ partial (composite key ရဲ့ အပိုင်း တစ်ခုပေါ်ပဲ) ဒါမှမဟုတ် transitive (တခြား non-key column ကနေတစ်ဆင့်)။ ဒီ စကားလုံး သုံးလုံးထဲက တစ်လုံးကို English လို ရိုက်ထည့်ပါ။
| အခြေအနေ | Dependency အမျိုးအစား |
|---|---|
Composite PK (PlotID, SeasonYear) ပါတဲ့ table RENTAL(PlotID, SeasonYear, SizeM2, GardenerID)။ SizeM2 က PlotID ပေါ်မှာပဲ မှီခိုပါတယ်။ | |
PK EmpID ပါတဲ့ table EMPLOYEE(EmpID, DeptID, DeptName)။ DeptName က DeptID ပေါ် မှီခိုပြီး DeptID က EmpID ပေါ် မှီခိုပါတယ်။ | |
PK CustID ပါတဲ့ table CUSTOMER(CustID, Email)။ CustID ကို သိရင် တူညီတဲ့ Email တစ်ခုတည်းကို အမြဲ ရပါတယ်။ | |
Composite PK ပါတဲ့ table ENROLMENT(StudentID, ClassID, ClassTitle)။ ClassTitle က ClassID ပေါ်မှာပဲ မှီခိုပါတယ်။ | |
PK BookID ပါတဲ့ table BOOK(BookID, PublisherID, PublisherCountry)။ PublisherCountry က PublisherID ပေါ် မှီခိုပြီး PublisherID က BookID ပေါ် မှီခိုပါတယ်။ |
Fill in the Blanks (ကွက်လပ် ဖြည့်ခြင်း)
Normal form သုံးမျိုးရဲ့ ဖော်ပြချက်ကို ပြီးအောင် ဖြည့်ပါ။ ဖော်ပြချက်ကို English လို ရေးထားပြီး အဖြေတွေကိုလည်း English လို ရိုက်ထည့်ပါ။
NORMAL FORMS
============
1NF requires every cell to hold a single, value
and that there are no repeating groups of columns.
2NF requires the table to be in 1NF and that there are no
dependencies. This matters when a key made
of two or more columns can identify each row.
3NF requires the table to be in 2NF and that there are no
dependencies between non-key columns.
The mnemonic phrase is "the key, the key,
and but the key."
စာကြောင်းတွေရဲ့ အဓိပ္ပာယ်: 1NF မှာ cell တိုင်းက ___ တန်ဖိုး တစ်ခုတည်း ရှိရမယ်၊ ထပ်ခါထပ်ခါ ပါတဲ့ column အုပ်စု မရှိရဘူး။ 2NF မှာ table က 1NF ဖြစ်ပြီး ___ dependency မရှိရဘူး၊ ဒါက column နှစ်ခု ဒါမှမဟုတ် ပိုများတဲ့ column တွေနဲ့ ဖွဲ့ထားတဲ့ key က row တစ်ခုချင်းကို ခွဲခြားသိစေနိုင်တဲ့အခါ အရေးကြီးပါတယ်။ 3NF မှာ table က 2NF ဖြစ်ပြီး non-key column တွေကြားမှာ ___ dependency မရှိရဘူး။ နောက်ဆုံး စာကြောင်းက မှတ်စရာ စကားစု "the key, the ___ key, and ___ but the key" ကို ဖြည့်ခိုင်းတာပါ။
Spot the Error (အမှား ရှာခြင်း)
ကျောင်းသား တစ်ယောက်က normal form သုံးမျိုးအကြောင်း ပြန်လှန် လေ့လာဖို့ မှတ်စု ရေးထားပါတယ်။ Line တစ်ကြောင်းမှာ အမှား ပါနေပါတယ်။ အမှားပါတဲ့ line ကို ရွေးပါ၊ ပြီးရင် မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ။
Line တွေရဲ့ အဓိပ္ပာယ်: line 1 က 1NF မှာ cell တိုင်း atomic တန်ဖိုး တစ်ခုတည်း ရှိပြီး repeating group မရှိဘူး၊ line 2 က 2NF ဆိုတာ 1NF ဖြစ်ပြီး non-key column တိုင်းက primary key တစ်ခုလုံးပေါ် မှီခိုတာ၊ line 3 က partial-key dependency ဖြစ်ဖို့ column နှစ်ခု ဒါမှမဟုတ် ပိုများတဲ့ column တွေနဲ့ ဖွဲ့ထားတဲ့ key လိုတယ်၊ line 4 က 3NF ဆိုတာ 2NF ဖြစ်ပြီး multi-valued dependency တိုင်းကို ဖယ်ရှားပြီးသား ဖြစ်တာ၊ line 5 က အချက် တစ်ခုတည်းကို နေရာ အများကြီးမှာ သိမ်းထားရင် update anomaly ဖြစ်တယ် လို့ ဆိုလိုပါတယ်။
Line 4 အတွက် မှန်ကန်တဲ့ ပြင်နည်းကို ရွေးပါ:
Identify the Normal Form (ဘယ် normal form ဖြစ်လဲ ခွဲခြားခြင်း)
Table GARDENER(GardenerID, GardenerName, MemberType, DutyHours) ရဲ့ primary key က GardenerID ပါ။ DutyHours ရဲ့ တန်ဖိုးက စိုက်ပျိုးသူရဲ့ MemberType အတွက် သတ်မှတ်ထားတဲ့ နာရီနဲ့ အမြဲ ကိုက်ညီပါတယ်။
ဒီ table က လက်ရှိ ရောက်နေတဲ့ အမြင့်ဆုံး normal form က ဘာလဲ။ (1NF, 2NF ဒါမှမဟုတ် 3NF လို့ ရိုက်ထည့်ပါ။)
Table RENTAL(PlotID, SeasonYear, GardenerID, ZoneCode) ရဲ့ composite primary key က (PlotID, SeasonYear) ပါ။ ဘယ်ရာသီမှာ ငှားငှား ZoneCode က PlotID နဲ့ ခွဲခြားသိရတဲ့ စိုက်ကွက်ရဲ့ ဇုန်နဲ့ အမြဲ ကိုက်ညီပါတယ်။
ဒီ table က လက်ရှိ ရောက်နေတဲ့ အမြင့်ဆုံး normal form က ဘာလဲ။ (1NF, 2NF ဒါမှမဟုတ် 3NF လို့ ရိုက်ထည့်ပါ။)
Practice Exercises (လေ့ကျင့်ခန်းများ)
မေးခွန်းတိုင်းမှာ ပါတဲ့ [3 marks] လို mark allocation (မေးခွန်း တစ်ခုစီအတွက် ပေးတဲ့ အမှတ်) တွေက IB စာမေးပွဲ ပုံစံအတိုင်း ပေးထားတာပါ။
Core (အခြေခံ အဆင့်)
-
[Core]Normalisation[3 marks]Table တစ်ခု 1NF, 2NF နဲ့ 3NF တစ်ခုချင်းစီ ဖြစ်ဖို့ ဘာတွေ လိုအပ်သလဲ State (ဖော်ပြပါ) (normal form တစ်ခုကို စာကြောင်း တစ်ကြောင်းစီ)။ -
[Core]Normalisation[2 marks]တောင်တက် လေ့ကျင့်ရေး အားကစားရုံ (climbing gym) တစ်ခုက လာရောက်မှု တိုင်းကို primary keyVisitIDပါတဲ့ table တစ်ခုတည်းVISIT(VisitID, VisitDate, ClimberID, ClimberName, ClimberPhone)မှာ မှတ်ပါတယ်။ တောင်တက်သူ အသစ် တစ်ယောက်က အဖွဲ့ဝင်ကြေး ပေးပြီး အဖွဲ့ဝင် ဖြစ်ထားပေမယ့် တစ်ခါမှ မလာရသေးပါဘူး။ တောင်တက်သူ အသစ်ရဲ့ အချက်အလက်တွေကို သိမ်းဖို့ ကြိုးစားတဲ့အခါ အားကစားရုံမှာ ဖြစ်တဲ့ ပြဿနာကို Identify (ဖြစ်နိုင်တဲ့ အဖြေတွေထဲက ရွေးပြီး ဖော်ပြပါ) လုပ်ပြီး 3NF design က ဒီပြဿနာကို ဘယ်လို ရှောင်ရှားသလဲ outline လုပ်ပါ။ -
[Core]Normalisation[2 marks]ဖွဲ့စည်းပုံဆိုင်ရာ တိကျတဲ့ ကွာခြားချက် တစ်ခုကို သုံးပြီး 1NF နဲ့ 2NF ကို Distinguish (အရာ နှစ်ခု ဒါမှမဟုတ် ပိုများတဲ့ အရာတွေကြားက ကွာခြားချက်ကို ရှင်းရှင်းလင်းလင်း ပြပါ) လုပ်ပါ။
Extension (တိုးချဲ့ အဆင့်)
-
[Extension]Normalisation[4 marks]ပါဆယ် ပို့ဆောင်ရေး ကုမ္ပဏီ တစ်ခုက သူ့ ပါဆယ်တွေကို primary keyParcelIDပါတဲ့ ဒီ table မှာ သိမ်းပါတယ်:PARCEL(ParcelID, WeightKg, SenderID, SenderName, DepotCode, DepotTown, DepotPhone)ပို့သူ တစ်ယောက်ချင်းစီမှာ နာမည် တစ်ခုတည်း ရှိပါတယ်။ Depot (ပါဆယ် စခန်း) တစ်ခုချင်းစီကို သူ့
DepotCodeနဲ့ ခွဲခြားသိရပြီး depot တစ်ခုစီက မြို့ တစ်မြို့တည်းမှာ ရှိကာ ဖုန်းနံပါတ် တစ်ခုတည်း ရှိပါတယ်။ ဒီ table က ဘာကြောင့် 3NF မဖြစ်သလဲ Outline လုပ်ပြီး 3NF ကို ချိုးဖောက်နေတဲ့ transitive dependency တွေကို identify လုပ်ပါ။ -
[Extension]Normalisation[5 marks]ကျောင်းများ အကြား စကားစစ်ထိုးပွဲ (debating tournament) တစ်ခုက ပွဲစဉ် (round) တစ်ခုစီမှာ ဟောပြောသူ (speaker) တစ်ယောက်စီ ရတဲ့ အမှတ်တွေကို မှတ်ပါတယ်။ Table က composite primary key(RoundID, SpeakerID)နဲ့ 1NF ဖြစ်ပါတယ်:ROUND_SPEAKER(RoundID, SpeakerID, RoundDate, VenueCode, VenueName, SpeakerName, TeamCode, TeamName, Points)ပွဲစဉ် တစ်ခုချင်းစီကို ရက်စွဲ တစ်ရက်မှာ ပွဲနေရာ (venue) တစ်ခုမှာ ကျင်းပပြီး venue code တစ်ခုစီမှာ venue နာမည် တစ်ခုတည်း ရှိပါတယ်။ ဟောပြောသူ တစ်ယောက်ချင်းစီမှာ နာမည် တစ်ခုတည်း ရှိပြီး အသင်း တစ်သင်းအတွက် ဟောပြောပါတယ်၊ team code တစ်ခုစီမှာ အသင်း နာမည် တစ်ခုတည်း ရှိပါတယ်။ ဟောပြောသူ တစ်ယောက်က သူ ဟောပြောတဲ့ ပွဲစဉ် တိုင်းမှာ အမှတ် ရပါတယ်။ Table ထဲက row လေးကြောင်းက ဒီလိုပါ:
RoundID SpeakerID RoundDate VenueCode VenueName SpeakerName TeamCode TeamName Points R1 S1 2026-03-07 V2 Hill Hall Noor A. T4 Eastwood A 72 R1 S2 2026-03-07 V2 Hill Hall Leo K. T5 Bayside B 70 R2 S1 2026-03-14 V3 Quay Room Noor A. T4 Eastwood A 75 R2 S3 2026-03-14 V3 Quay Room Mei T. T5 Bayside B 69 ကျောင်းသား တစ်ယောက်က ဒီ 2NF design ကို အဆိုပြုပါတယ်: primary key
RoundIDပါတဲ့ROUND(RoundID, RoundDate, VenueCode, VenueName, SpeakerID)နဲ့ primary keySpeakerIDပါတဲ့SPEAKER(SpeakerID, SpeakerName, TeamCode, TeamName, Points)။ ကျောင်းသားရဲ့ design က မှတ်တမ်းတင်လို့ မရတဲ့ နမူနာ row တွေထဲက အချက် နှစ်ခုကို Identify လုပ်ပြီး design က ဘာကြောင့် အဲဒါတွေကို ဆုံးရှုံးသလဲ explain လုပ်ပါ။ ပြီးရင် အချက်တိုင်းကို ထိန်းထားနိုင်တဲ့ 2NF design တစ်ခုကို primary key နဲ့ foreign key အားလုံး ပြပြီး construct (ကိုယ်တိုင် တည်ဆောက်ပါ) လုပ်ပါ။ -
[Extension]Normalisation[6 marks]မေးခွန်း 5 က 2NF schema ကို ယူပြီး ဆက် normalise လုပ်ပါ။ ဖယ်ရှားလိုက်တဲ့ transitive dependency မှန်သမျှကို ဖော်ပြရင်း 3NF schema ကို Construct လုပ်ပါ။ Primary key တိုင်းနဲ့ foreign key တိုင်းကို ပြပါ။
Challenge (စိန်ခေါ်မှု အဆင့်)
-
[Challenge]Normalisation[8 marks]ရပ်ကွက် ဂီတ ကျောင်း တစ်ခုက သင်ခန်းစာတွေကို ဒီ table တစ်ခုတည်းနဲ့ မှတ်ပါတယ်:LESSON(LessonID, StudentID, StudentName, StudentPhone, TeacherID, TeacherName, Instrument, LessonDate, RoomNumber, RoomBuilding)သင်ခန်းစာ တစ်ခုစီက ကျောင်းသား တစ်ယောက်အတွက်၊ ဆရာ တစ်ယောက်နဲ့၊ တူရိယာ တစ်မျိုးနဲ့၊ အခန်း တစ်ခန်းမှာ ဖြစ်ပါတယ်။ ကျောင်းသားတွေနဲ့ ဆရာတွေ တစ်ယောက်ချင်းစီက တူရိယာ အမျိုးမျိုး တီးနိုင်ပါတယ်၊ ကျောင်းသား တစ်ယောက်ချင်းစီက ဆရာ အများကြီးဆီက သင်ခန်းစာ ယူပြီး ဆရာ တစ်ယောက်ချင်းစီက ကျောင်းသား အများကြီးကို သင်ပါတယ်။ ကျောင်းသား တစ်ယောက်ချင်းစီမှာ နာမည် တစ်ခုနဲ့ ဖုန်းနံပါတ် တစ်ခုတည်း ရှိပြီး ဆရာ တစ်ယောက်ချင်းစီမှာ နာမည် တစ်ခုတည်း ရှိပါတယ်၊ အခန်း ရှိတဲ့ အဆောက်အအုံကို အခန်း နံပါတ် တစ်ခုတည်းက ဆုံးဖြတ်ပါတယ်။
3NF schema ကို Construct လုပ်ပါ။ Primary key အားလုံး၊ foreign key အားလုံးနဲ့ အဆင့်တိုင်းမှာ ဖယ်ရှားခဲ့တဲ့ dependency တွေကို ဖော်ပြပါ။
-
[Challenge]Normalisation[6 marks]Online သတင်း website တစ်ခုရဲ့ homepage က သတင်းခေါင်းစဉ် တစ်ခုစီကို စာရေးသူရဲ့ နာမည်နဲ့ ဓာတ်ပုံနဲ့အတူ ပြပါတယ်။ Website က homepage ကို တစ်ရက်မှာ အကြိမ် သန်းချီ load လုပ်ပါတယ်၊ စာရေးသူတွေက သူတို့ ဓာတ်ပုံကို တစ်နှစ်မှာ တစ်ကြိမ်လောက်ပဲ ပြောင်းကြပါတယ်။ စာမျက်နှာ load လုပ်တိုင်းAUTHORtable နဲ့ join လုပ်မယ့်အစား article row တစ်ခုစီမှာ စာရေးသူရဲ့ နာမည်နဲ့ ဓာတ်ပုံ URL (website လိပ်စာ) ကို သိမ်းပြီး developer (software ရေးသူ) တွေ denormalise လုပ်သင့်မလား Evaluate လုပ်ပါ။
Exam-Style (စာမေးပွဲ ပုံစံ မေးခွန်း)
-
[Exam-Style]Normalisation[5 marks]ကူးတို့ သင်္ဘော ကုမ္ပဏီ တစ်ခုက ခရီးစဉ် (crossing) တစ်ခုစီမှာ တင်ဆောင်တဲ့ ယာဉ်တွေကို table တစ်ခုတည်းမှာ မှတ်ပါတယ်။ အဲဒီ table က composite primary key(CrossingID, VehicleReg)နဲ့ 1NF ဖြစ်ပါတယ်:CROSSING_LOG(CrossingID, VehicleReg, CrossingDate, Route, VehicleType, FarePaid)ခရီးစဉ် တစ်ခုက ယာဉ် အများကြီး တင်ဆောင်ပြီး ယာဉ် တစ်စီးတည်းက ခရီးစဉ် အများကြီးမှာ လိုက်ပါနိုင်ပါတယ်။ ခရီးစဉ် တစ်ခုစီမှာ ရက်စွဲ တစ်ခုနဲ့ လမ်းကြောင်း (route) တစ်ခုတည်း ရှိပါတယ်။ ယာဉ် တစ်စီးချင်းစီကို သူ့ မှတ်ပုံတင် နံပါတ် (
VehicleReg) နဲ့ ခွဲခြားသိရပြီး အမျိုးအစား တစ်မျိုးတည်း ရှိပါတယ်၊ ဥပမာ ကား၊ ဗင်ကား ဒါမှမဟုတ် ဆိုင်ကယ်။ ခရီးစဉ် တစ်ခုစီမှာ ယာဉ် တစ်စီးစီအတွက် ခရီးစရိတ် ပေးရပြီး ခရီးစဉ် တစ်ခုတည်းမှာ အမျိုးအစား တူတဲ့ ယာဉ် နှစ်စီးက မတူတဲ့ ခရီးစရိတ် ပေးနိုင်ပါတယ် (တစ်စီးက စောစော ကြိုတင် စာရင်းသွင်းထားလို့ ဈေးသက်သာ ရနိုင်ပါတယ်)။ Primary key တိုင်းနဲ့ foreign key တိုင်းကို ပြပြီး 2NF schema ကို Construct လုပ်ပါ၊ ပြီးရင် ဖယ်ရှားခဲ့တဲ့ partial-key dependency တွေကို state လုပ်ပါ။
IB CS သင်တန်း တက်နေသူတွေအတွက် မှတ်ချက်: ပြည့်စုံတဲ့ 3NF design မှာ table တိုင်းကို သူ့ရဲ့ primary key နဲ့ foreign key တွေနဲ့အတူ ပြရပါတယ်၊ တန်ဖိုး တစ်ခုထက် ပိုသိမ်းထားတဲ့ field (record တစ်ခုထဲက အချက်အလက် တစ်ကွက်) မှန်သမျှကို field တိုင်း atomic ဖြစ်အောင် ခွဲရပါတယ်၊ ပြီးတော့ table တွေကို မှန်ကန်တဲ့ foreign key တွေနဲ့ ချိတ်ရပါတယ်။ ဒီအဆင့်မှာ ပုံမှန် design တစ်ခုမှာ table သုံးခုကနေ ငါးခုအထိ ရှိပါတယ်။ Denormalisation (A3.2.7) အတွက် read-heavy နဲ့ write-heavy (ရေးတာ များတဲ့) အသုံးပြုမှုကို ချိန်ဆနိုင်ရပါမယ်၊ လက်ရှိ တန်ဖိုး တစ်ခုရဲ့ မိတ္တူ (redundancy) နဲ့ ဖြစ်ရပ် တစ်ခု ဖြစ်တဲ့အချိန်မှာ မှတ်ထားတဲ့ တန်ဖိုး (ဥပမာ ပါဆယ်ကို ပို့ခဲ့တဲ့ လိပ်စာ) ကို ခွဲခြားနိုင်ရပါမယ်၊ integrity (ဒေတာ မှန်ကန်ပြီး မပျက်စီးဘဲ ရှိနေခြင်း) နဲ့ performance (မြန်နှုန်း) ကို ချိန်ညှိနိုင်ရပါမယ်။
ဆက်စပ် ခေါင်းစဉ်များ
- အရင် လေ့လာထားရမယ့် ခေါင်းစဉ်: Data Types and Keys (ဒေတာ အမျိုးအစားနဲ့ key များ)။ Normalisation က table တွေကို ထုတ်ပေးပြီး key တွေက အဲဒီ table တွေကို ချိတ်ပေးပါတယ်။
- ဆက်စပ် ခေါင်းစဉ်: Entity-Relationship Diagrams။ 3NF schema တစ်ခုကို များသောအားဖြင့် table တစ်ခုကို entity (database ထဲမှာ ဒေတာ သိမ်းမယ့် အရာ တစ်ခု) တစ်ခုစီ၊ foreign key တွေကို relationship (ဆက်နွယ်မှု) တွေအဖြစ် ထားပြီး ERD (entity တွေနဲ့ ဆက်နွယ်မှုတွေကို ပြတဲ့ ပုံ) အဖြစ် ဆွဲနိုင်ပါတယ်။
- နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်: SQL Queries။
JOINclause (SQL statement ရဲ့ အစိတ်အပိုင်း) တွေက normalisation က ဖန်တီးပေးတဲ့ foreign key ချိတ်ဆက်မှုတွေ အတိုင်း table တစ်ခုကနေ တစ်ခုကို ဖြတ်သွားပါတယ်။ - နောက်ပိုင်း လေ့လာရမယ့် ခေါင်းစဉ် (HL: Higher Level၊ IB သင်တန်းမှာ ပိုနက်နက်ရှိုင်းရှိုင်း လေ့လာရတဲ့ အဆင့်): Data Warehouses။ တမင် denormalise လုပ်ထားတဲ့ database ရဲ့ စံပြ ဥပမာပါ၊ transaction update တွေအတွက် မဟုတ်ဘဲ ခွဲခြမ်းစိတ်ဖြာရေး query တွေအတွက် အကောင်းဆုံး ဖြစ်အောင် ဖွဲ့စည်းထားပါတယ်။
- နောက်ပိုင်း လေ့လာရမယ့် ခေါင်းစဉ် (HL): Transactions and Views။ View (query ရလဒ်ကို table တစ်ခုလို ကြည့်လို့ရအောင် database ထဲမှာ သိမ်းထားတဲ့ object) တွေက normalise လုပ်ထားတဲ့ schema ပေါ်မှာ denormalise လုပ်ထားသလို မြင်ရတဲ့ interface (အပြင်ကနေ သုံးရတဲ့ ပုံစံ) ကို ပေးနိုင်ပြီး နှစ်ဘက်လုံးရဲ့ အကောင်းဆုံးကို ရစေပါတယ်။