--- tags: 大學筆記系列 --- # 資料庫系統 ## 課程網頁 https://www.cs.ccu.edu.tw/~damon/secure/course-wk.html 帳號:cornell 密碼:bigred ## 第一章: 導論 ### 名詞解釋 1. schema: 藍圖,database的定義(cloumn) 2. instance: 存在database中的資料(row) ### 完整流程: 1. Defining: **定義**資料庫 2. Constructing: **加入**資料 3. Manipulating: **查詢**資料(query) ### Relational Model:最常用的儲存資料的模型 A **row** is a **record**. A **column** is a **field** or **attribute**. ![](https://i.imgur.com/n2y3HtK.png =85%x) ### Data Definition Language (DDL) 資料定義語言, ### Data Manipulation Language (DML) 資料操作語言, ## 第二章: Entity-Relationship Model ![](https://i.imgur.com/R5t3N6x.png) ### 資料庫設計流程 1. Requirements Analysis: 分析需求 * 要儲存甚麼**資料** * 要**應用**在哪裡 2. Conceptual Database Design: 設計資料庫架構 * Entity-Relation (ER) model * **本章重點** 3. : Logical Database Design: 實做資料庫 ### **key** vs. **foreign key** * 藍色的為 key,必須是唯一的 * 紅色的是 foreign key,是外來的key,可以透過這個來對應至別的table中的資料 ![](https://i.imgur.com/kT53Up4.png) 觀念釐清: (X) 每個table都有一個獨一無二的key ### Entities and Attributes * domain: 每個attribute可能值的範圍(ex:int) * entity(實體): 對應到現實世界中的物件(ex:學生)等,由一系列的attribute(ex:姓名,電話)組合而成 * entity set: 由一堆同型態的entity所組成,相當於table ![](https://i.imgur.com/pC30qWk.png =90%x) ### Keys * superKey: 若數個attribute合在一起能**唯一決定**一個entity,則稱這個由attribute組成的**集合**為superKey * Key/candidate key: 若數個attribute合在一起能**唯一決定**一個entity,**且所需attribute數量最少**,則稱這個由attribute組成的**集合**為Key/candidate key * primary key: 最終選擇的那個key 觀念釐清: (X) 一個表格中的superKey一定是唯一的 (X) 一個表格中的Key一定是唯一的 (O) 全部attribute合起來必定是superKey ### Relationships * 指兩個entity之間的關係,**可以一對多**,**兩個entity順序不可對調** * Relationship也可以有attribute ![](https://i.imgur.com/IwTBVKM.png) * Relationship 也可以是遞迴的(對應到自己) ![](https://i.imgur.com/7kqqXd0.png =50%x) 觀念釐清: (O) 一個relation必須可只由參與的entity決定,不需要包含本身的attribute ### Key Constraints * 觀察Mother-Child的**一對多**relationship ![](https://i.imgur.com/39X6dXt.png =80%x) * 一個Mother中的entity 可能對應至0,1,2...個Child中的entity -->**不適合當key** * Child 具有Key Constraints,可以**最多只對應至一個**Mother中的entity -->**適合當key** * Key Constraints 以**箭頭**表示 * Tip: 連出去只能有一個的那方虛畫箭頭指出去 ![](https://i.imgur.com/Ow3YfHK.png) * **一對一**的關係兩個方向都有Key Constraints * **多對多**的關係沒有Key Constraints 觀念釐清: 有key constraint的那方的key可直接作為所參與relation的key ### participation constraint * 分成兩類: * total participation: 每筆entity中的資料都參與某個relationalship (以粗線表示) * partial: 部分entity沒參與任何relationalship ### strong entity v.s. weak entity * strong entity: **必須要有super key** * weak entity: **沒有super key**,需要透過其他entity的primary key的幫助,才能唯一決定每筆entity中的資料,**需用粗框框標示weak entity及有關的relationship** 1. partial key: 在weak entity 中,若透過其他entity(Owner) 的幫助,partial key 便可唯一決定每筆資料,**以虛線表示** 2. Owner 跟 weak entity關係一定是**一對多** 3. weak entity **一定要 total participation** ![](https://i.imgur.com/jI2fu0e.png) 觀念釐清: * connection trap: 超過兩個entity的relationship**不能**被兩兩一組的relationship取代 ![](https://i.imgur.com/pGd2vvX.png) ### Class Hierarchies * 舉個例子 ![](https://i.imgur.com/ZkJst97.png) * 將Employee分成兩個subclasses(Hourly-Emp,Contract_Emp) * subclasses繼承了Employee 的attribute(ID,name...),並各自擁有各自擁有的額外attribute(Hour_wages,Contract_ID) ### Aggregation * 可以把aggregation當成是一個entity * 從其中一個relationship產生另一個relationship * 用來化簡trnary relationship(三方參與的關係) * 舉個例子 ![](https://i.imgur.com/Cx81jaB.png) 可以先將Project跟Department**綁定(Aggregation)**,以降低複雜度 觀念釐清: 1. 要成為attribute,需要滿足以下條件 * 不可以是集合(cannot be set-valued) * ex: address同時有縣市、門牌號碼,則attribute便只能是entity * 不可被分割(atomic) 2. 要成為entity,需要滿足以下條件 * 至少有一個**non-key** attribute * 在多對一及多對多關係時,是**多**的那一方 ### 資料庫設計原則 * 盡可能減少**多餘**的attribute與entity * 盡可能將entity**替換**成attribute * 盡可能**不要使用**weak entity set ## 第三章 ### ER Model v.s. Relational Model * ER Model: 給人看的模型,甚至不能進行operation * Relational Model: 程式能實做出來的模型 ### 基本架構 * relation: * Relation instance:表格內的值,含row(tuples,cardinality)與column(field,degree) * Relation scheme:架構,第一個row的attribute 可以簡化成這樣 ![](https://i.imgur.com/50iEkQI.png =70%x) 觀念釐清: * (X) 一個Relation instance中的column必須是唯一的 ### SQL 語法---創建table 此table 可以用以下語法創建 ![](https://i.imgur.com/VisSsmZ.png) ![](https://i.imgur.com/ipiRrrX.png) * 可用的欄位型態可以為: integer(整數),real(浮點數),char(字串) ### SQL 語法---刪除table 使用以下指令: > drop table 表格名 ### SQL 語法---修改欄位 使用以下指令新增與刪除某個欄位 > > ex: alter table customer add phone char(10) > ex: alter table customer delete phone ### SQL 語法---插入資料 使用以下指令 > insert into students values > (410410054,'男'); ### SQL 語法---刪除資料 使用以下指令 > delete from students as S where S.name='Daniel' ### SQL 語法---修改資料 使用以下指令 > update students S > set S.gpa=5 > where S.name='Jason' ### Integrity Constraints(ICs) * 指資料受到某些條件的限制 * ex: not null * 又分成: * Domain constraint * Key constraint * Unique: 綁定其中兩個欄位,使之成為key * Foreign key constraint (referential integrity) * foreign key: 可以綁定外來的key,以保護資料庫  * 可以使用cascade關鍵字來連動其他表格做更新、刪除等動作 * 觀念釐清:foreign key可以是null,且必須對應到別的table中的primary key * Other constraints ### ER to relational model * 定義: 若weak entity W 依賴 strong entity E,則稱E owns W #### 將strong entity變成table 直接化成表格即可 ![](https://i.imgur.com/h8Db7Jq.png =70%x) ![](https://i.imgur.com/jkBUJEs.png =80%x) #### 將weak entity變成table 需要加上所依賴的那個實體的primary key ![](https://i.imgur.com/i45KzFU.png =70%x) ![](https://i.imgur.com/HW9aGBE.png =80%x) #### 將one to one 關係變成table 1. 優先將有total participation的那方與relationship合併 2. 加上沒被選擇的那方的primary key作為欄位 3. 加上該relationalship的attribute作為欄位 4. 沒被選擇的那方另開一個table儲存 ![](https://i.imgur.com/9ppessu.png) ![](https://i.imgur.com/RCmxW4A.png) ### 將one to many 關係變成table 1. 優先將有key constrant 的那方與relationship合併(將1那方的primary key作為attribute加入至many那方中) 2. 加上沒被選擇的那方的primary key作為欄位 3. 加上該relationalship的attribute作為欄位 4. 沒被選擇的那方另開一個table儲存 ![](https://i.imgur.com/OcOKzgP.png) ![](https://i.imgur.com/7qf8lrX.png) ### 將many to many 關係變成table 1. 三方各建一個table較佳 ![](https://i.imgur.com/1OalNOr.png) ![](https://i.imgur.com/lde4K2z.png) ### 將n-ary關係變成table 1. 各entity、relation各建一個table 2. 將有key constraint的entity的primary key作為relation的primary key ### 將ISA 關係變成table 1. 除了共同項以外,各建一個table,並把共同項的attribute加進table中 ![](https://i.imgur.com/26ID6kU.png =80%x) * 寫法1 ![](https://i.imgur.com/AaYEFKG.png) * 寫法2 ![](https://i.imgur.com/xJIsRY3.png =80%x) ### 將aggregation變成table ![](https://i.imgur.com/WYWrkP7.png) ## 第四章 ### SQL 語言分類 * Data Manipulation Language(DML):數據操作語言,包含提出查詢、插入、刪除和修改資料的相關語法 * Data Definition Language(DDL):數據定義語言,包含創建、刪除和修改table的定義。 * Trigger: 根據設定的條件動態的改變資料庫 ### DML語法 ![](https://i.imgur.com/eR5Um1N.png =50%x) * SELECT: 選擇要作為結果的欄位 * FROM: 選擇要交叉比對的table * WHERE: 限制 * DISTINCT: 表示答案不應包含重複項,代表此項可有可無 * 原理: 1. 計算relation-list交叉比對後的結果 2. 將不滿足qualification的結果捨棄 3. 刪除不再target-list中的attribute 4. 如果是DISTINCT,則刪除重複的資料 * 舉個簡單的例子 ![](https://i.imgur.com/b4TZDxP.png=50%x) * 從Loan這個表格中branch_name這個欄位,並挑出不重複的資料作為結果 * 舉個進階的例子 ![](https://i.imgur.com/0BqYT5i.png) * 從Sailors及Reserves兩個表格中交叉比對(row數相乘,column數相加) * 設定Sailors的別名為S,Reserves的別名為R( Range Variables) * 在進行自連接(self-join)時,一定要使用 ![](https://i.imgur.com/9AFZ6hB.png =70%x) * S.sid=R.sid這句用來連結兩筆資料 * R.bid=103這句用來限制選擇條件 * SELECT S.sname這句用來決定想要的result * SQL expression語法 ![](https://i.imgur.com/cQIXIwz.png) * AS: 自訂欄位名稱(例如自訂age1欄位,值為S.age-5) * =: 同AS * LIKE: 用來標示要使用regular expression * %: 0或更多的任意字元 * _: 1個任意的字元 * SQL 集合相關語法 ![](https://i.imgur.com/4iYE30n.png) * 兩段程式碼等價 * Union(聯集) 可以替換成INTERSECT(交集)、EXCEPT(差集) * 要保留重複的資料,加上保留字ALL(ex: UNION ALL) * 巢狀quary ![](https://i.imgur.com/5hTyQ1n.png) * IN 的邏輯為"屬於"(可以取代INTERSECT) * subquery會先做 * Correlated 巢狀quary ![](https://i.imgur.com/U3ehkdW.png) * EXIST 的邏輯是"至少有一個(非空集合)" * 與EXIST 類似的邏輯還有UNIQUE,邏輯為"最多一個" * Tip:雙重否定可以用在找"全部都要符合"的條件,變換成"刪掉任一個不符合的" * Set-Comparison Operators ![](https://i.imgur.com/tZeH58I.png) * 此題的意思是找出Sailors中rating大於任何一個名字為"Horatio"的rating的所有人 * ANY 的邏輯為"任何" 相同用法的還有'ALL',邏輯為"全部" * Division in SQL ![](https://i.imgur.com/MYtARAH.png) * Aggregate Operators ![](https://i.imgur.com/dyRx6xA.png) * SQL 內建簡單的運算邏輯,共有五種可使用 ![](https://i.imgur.com/jzfSX6d.png =80%x) 不可這樣寫,否則name與age會變成多對一關係 ![](https://i.imgur.com/9SVRFZd.png =80%x) 正確寫法 ![](https://i.imgur.com/i3rcGgU.png =80%x) 觀念釐清:aggregate operations 不支援巢狀 * Group by and Having * Group by的邏輯為"分群" * Tip: Group by的attritube可以為多個 * Having 的邏輯與where一樣,用來修飾group,因為不能有重複的where才多設定這個語法 * 觀念釐清: 只有出現在Group by的attribute才會被having 參考 ![](https://i.imgur.com/Qe9eJDH.png) ![](https://i.imgur.com/PFHOfV6.png =80%x) 觀念釐清: ![](https://i.imgur.com/xs9Kwwc.png) * count 會在where s.age>18那行執行結束後才執行,這樣會過濾掉那些"剛好要加入<=18歲水手才能湊成兩個人"的那些group * 利用subquary會先執行的特性,可以改寫此邏輯,如此一來where s.age>18會最後才判斷 特殊用法: ![](https://i.imgur.com/Z6qZzAg.png) ![](https://i.imgur.com/u1Kj6Pt.png) * sorting result 加上: ORDER BY column [ ASC | DESC][, ...] 預設是遞增,若想遞減,在最後加上DESC * 面對多層select時的邏輯判斷技巧: 1. 雙重否定邏輯: 把都沒有的給刪掉 2. 表格比對法: ![](https://i.imgur.com/ozIl7Co.png) 3. 字面邏輯觀察法 * exist 與 in 等效轉換 * select A.Branch from Holdings A where exists ( select * from Titles B where B.Author = 'Ann Brown' and B.Title = A.Title); * select A.Branch from Holdings A where A.Title in ( select B.Title from Titles B where B.Author = 'Ann Brown'); ### join 分成數種: 1. inner join...on 條件 * 相當於relational algebra中不加任何條件的join 2. left join * 保留了左部分表格中的所有row,若右邊沒有順利匹配到,則補NULL * ![](https://hackmd.io/_uploads/rkk8tzKIh.png) 3. right join * 保留了右部分表格中的所有row,若左邊沒有順利匹配到,則補NULL * ![](https://hackmd.io/_uploads/SyrvtzYIh.png) 4. full join * 同時具有left join及right join的性質 * ![](https://hackmd.io/_uploads/Syt_KfKIh.png) ## 第八章 B-tree * 想解決一般的binary tree 的深度過深的問題 -> 創建多層indexes,每層稱為**index page** ![](https://i.imgur.com/hVdy6kq.png) ### ISAM * 屬於Index pages是靜態的,必須假設資料量並不會變動太多 * 每個節點為<search key value, page id> * 分成三層: 1. Index pages: 路標,用來決定要往哪裡搜尋資料 2. Data pages: 真正存資料的地方 3. Overflow pages: 若有兩筆資料應該要放在同一個地方,那就需要使用類似linked_list的概念串在底下 **優點**: 當資料量不大時,能處理得很好 **缺點**: 若資料集中在某個區間,會導致Overflow pages過大,搜尋效率降低 ![](https://i.imgur.com/l3K4jmg.png =80%x) * 有星號的代表真正的資料,沒有則代表路標 * next-leaf-page pointer(連結15與20的指標): 方便range search(ex: 找比15大的所有資料) 觀念釐清: 1. (O)一個table底層可能不只一棵tree 2. (O)search key value可能不是所代表table的primary key ### B+ Tree (此圖非B+ tree,只適用於名詞解釋) ![](https://i.imgur.com/oauh8wa.png) * root: 根節點 * internal node: 中間的那些點 * leaf: 沒有child的那些點 * height: 3 (4-1),從root至leaf所走的距離 * balanced: * leaf node都在同一層 * 避免搜尋資料所花的時間non-deterministic ![](https://i.imgur.com/A3xEw5C.png =30%x) 特性: 1. 沒有overflow chain 2. leaf page及每個路標(internal)內的資料已排序 3. Index pages會隨著資料動態改變 4. 能將大小類似的資料一次讀到主記憶體(一整個node) * B+ Tree internal node 結構 ![](https://i.imgur.com/UlCFfds.png) * K 是路標 * P 是指向下一層的pointer * 定義order(d) 代表該node路標數的限制 -> d<=n<=2d(root不用滿足) * B+ Tree leaf node 結構 ![](https://i.imgur.com/KJ5tSwQ.png) (ki,ri) 合併稱為ki*(* 代表真實的資料,非路標) * B+ tree範例 ![](https://i.imgur.com/4wMBzOY.png) * B+ tree搜尋 ![](https://i.imgur.com/ndYOVze.png) 以這個例子來說,分別搜尋 1. 5 2. 15 3. \>=24 * B+ tree插入 * case1: 插入前leaf還沒滿 -> 直接新增資料 * case2: 插入前leaf已滿 -> 分成兩個新node,並遞迴的更新上面的節點 舉例: 1. 原圖 ![](https://i.imgur.com/ktekxy8.png) 2. 插入 *16(case 1) ![](https://i.imgur.com/ZiPH5OB.png) 3. 插入 *8 ->左下節點已經滿了(case 2) ![](https://i.imgur.com/klQ16SU.png) 4. 分割成兩個節點 ![](https://i.imgur.com/mLYoJXW.png) 5. copy up 右節點的第一個數字,加入至上層 ![](https://i.imgur.com/DHp6ckD.png) 6. 上層節點也已滿 ![](https://i.imgur.com/9NgmHAt.png) 7. 分割成兩個節點 ![](https://i.imgur.com/flCM600.png) 8. push up 右節點的第一個數字,加入至上層,若上層為root,將此數字節點當root,樹變高一層,結束 ![](https://i.imgur.com/BKCqHZ7.png) 註: 1. 若「右節點的第一個數字」是真實資料,則須採用"copy up"的方式,複製一個同樣的數字加到上層 2. 若「右節點的第一個數字」是路標,則須採用"push up"的方式,直接將該數字移動到上層 補充:還有一種方式叫做redistribution,但實作困難,所以通常不做 ![](https://i.imgur.com/P69NxdZ.png) * B+ tree 刪除 簡單版: 若沒找到該筆欲刪除的資料,則直接返回 若找到了,刪除它 刪除後如果該節點變為空,則移除這個節點 困難版: case 1: 1. 刪除19,node元素數量>=order,沒事 ![](https://hackmd.io/_uploads/H1armmurh.png) 2. 刪除20,node元素數量<order,要處理 3. 若同屬同一個parent的鄰居還夠,跟鄰居借一個數字來補 4. 補完後記得將更新parent (24換成27) ![](https://hackmd.io/_uploads/SJxHVXdB2.png) case 2: 1. 刪除24,node元素數量<order,要處理 ![](https://hackmd.io/_uploads/HkIeVQ_S2.png) 2. 同屬同一個parent的鄰居也不夠借,跟鄰居合併 3. 刪除原本用於區分兩個合併前node的parent中的數字(27) 4. 該parent的路標數也不夠了,隔壁也沒得借,再與隔壁合併 5. 發現上層(root)沒得刪(不可能刪掉17),把17抓下來合併成新的root ![](https://hackmd.io/_uploads/HJ1SrQurh.png) * Prefix Key Compression 若資料的開頭都不一樣,在設置路標時,便可以省略部分名字 ex: 區分deniel,devC++,damon的路標可以設成den,dev,dam即可 (留Prefix) * Suffix Key Compression 若資料的開頭都一樣,在設置路標時,便可以將一樣的開頭記起來,並以結尾不同的部分作為路標即可 (留Suffix) * Bulk Loading of a B+ Tree 將待插入的資料先排序好,在插入時B+ Tree會更漂亮 ![](https://i.imgur.com/1dxFu0h.png) ## 第六章 Relational algebra: 屬於procedural query language,是實際操作步驟,例如bubble sort演算法步驟 Relational calculus: 讓使用者描述他們想要什麼,例如"排序"兩字 ### 六種relation algebra基礎的運算符號(用來處理集合運算) 這些運算符號會將一至兩個relation instances作為輸入,並輸出一個relation instance relation instances: (表格中的)真實資料 1. select ( σ) ![](https://i.imgur.com/fIzop8w.png) 2. project ( Π) ![](https://i.imgur.com/CxvO7sQ.png) * 因為是集合運算,故會移除重複的元素 3. union ( U ) ![](https://hackmd.io/_uploads/r1cq0vwVn.png) 4. set different ( -) ![](https://hackmd.io/_uploads/Sk1nRPD42.png) * R-S !=S-R * intersect = R-(R-S) 5. Cartesian product ( x ) ![](https://hackmd.io/_uploads/BkIC1OPV3.png) 6. rename ( ρ) ![](https://hackmd.io/_uploads/SJqjJ_wN3.png) * 將E中的欄位重新命名,結果為C 範例(materialized): ![](https://hackmd.io/_uploads/r1eBWOw42.png) 1. 從Employee中選擇女員工,作為Female_emps ![](https://hackmd.io/_uploads/rJDwWdDEh.png) 2. 從Female_emps選取必要欄位 ![](https://hackmd.io/_uploads/H1lqZuvV2.png) 3. 與Dependents做cross product ![](https://hackmd.io/_uploads/H1sIGuwN2.png) 4. 選取id=eid的那些欄位 ![](https://hackmd.io/_uploads/H1sOMuPNn.png) 5. 選擇欄位作為結果 ![](https://hackmd.io/_uploads/HJ19fdvV2.png) 觀念釐清: materialized: 預先計算 on-the-fly: 即時計算 ### 特殊運算符號--join 目的是取代"X followed by σ" * condition join 上述範例的第3,4步可被替換成 ![](https://hackmd.io/_uploads/rJSD7dwV2.png) 使用範例: ![](https://hackmd.io/_uploads/B1l6VdDV2.png) * 先找到薪水小於某人的所有員工,再用全體員工減去即可 * (F,Employee)目的是將Employee的別名設置成F * 只有在有重複欄位的情況下(自己跟自己join),才需要將條件寫成Employee.salary指名要選的salary是Employee的還是F的 * project,set different的先後順序不影響結果 * Equi-Join 只包含equalities的condition join ![](https://hackmd.io/_uploads/BJEk__PN3.png) * Natural Join(join) 屬於Equi-Join,但equalities的條件是所有R與S中共有的欄位 ![](https://hackmd.io/_uploads/rk25OdPV3.png) 相當於R.b=S.b and R.d=S.d ### Division 舉例: A/B2 會將A先對X分群(分成X1-X4),接著將"包含所有B2中的元素的那些X"給選出來(即回傳的是滿足條件的x欄位) ![](https://hackmd.io/_uploads/r1KvU_DE3.png) * 對應至SQL語法的"all"邏輯 ### 結論 Relational algebra 是 operational(操作性)的 ## 第七章(考很少) Domain Relational Calculus(DRC): ![](https://hackmd.io/_uploads/rJet5dPEn.png) 只能使用以下運算子 ![](https://hackmd.io/_uploads/S1MjsuP4h.png) 舉例: ![](https://hackmd.io/_uploads/SJ1X2dv4h.png) ### 結論 Relational calculus 是 non-operational(非操作性)的,只講述query的要求,不考慮如何實作 ## 第十章 ### Static Hashing ![](https://hackmd.io/_uploads/H1MQdf543.png) * primary bucket pages 大小不會變動 * overflow pages 可能過多,導致搜尋效率變差 * range searches所花時間非常多 ### Extendible hashing ![](https://hackmd.io/_uploads/ry8TOG543.png) * 移除overflow pages * 當發生overflow時,將primary bucket pages變為兩倍,並重新rehash裡面的資料 為了解決rehash浪費時間的問題,設定了global depth跟local depth來解決 概念: 真的要將bucket分開的時候再分開 原圖 ![](https://hackmd.io/_uploads/Hy7-aMc4h.png =70%x) case 1: 1. 欲插入20(10100),20應該要進到bucket A,但該bucket已滿了,且local depth不能再提高(local depth必須 <= global depth) 3. 將directory變成兩倍;將bucket A 的depth變成3並分成兩邊;連結新的directory區塊至bucket B,C,D(暫時不拆分) ![](https://hackmd.io/_uploads/BkzH0McE2.png =70%x) case 2: ![](https://hackmd.io/_uploads/ByBLS1KLh.png) 1. 欲插入9 (001),發現已滿,但local depth還可再提高 2. 提高local depth,rehash已滿bucket裡面的內容 註: 此種hashing的方法在處理重複元素時可能還是需要overflow page,因為單純的split node後,重複元素仍會被rehash至同一個地方 ## 第九章 ### database 架構 ![](https://hackmd.io/_uploads/Sk983seHn.png) * SQL commend: 期中考內容 * DBMS: 第11章內容 * DATABASE: 本章內容 資料平常存在disk中,並透過 * READ: 將資料從disk中讀進主記憶體(Main Memory,RAM) * WRITE: 將資料從RAM寫進disk中 record: 相當於一個table file: 一個檔案中可能有很多table,table不可跨檔案儲存 page: 硬碟中的一個區塊,file可以跨page,但不能跨disk儲存 ### 儲存階級 ![](https://hackmd.io/_uploads/H1eKl2er3.png =50%x) ### 硬碟架構 ![](https://hackmd.io/_uploads/SJ2AZhxr3.png) * sector 是硬碟上的最小單位,Block size是sector size的倍數 * Disk head: 讀寫頭 從硬碟讀取資料時間分成三種 seek time: 找到正確的track的所需的時間 rotational delay: 旋轉spindle至正確位置所需的時間 transfer time(所需時間非常短): 從該位置讀寫資料所需的時間 將資料放在硬碟中的同一個區塊,可以更快讀取這些資料 ### RAID Redundant Arrays of Independent Disks 將多個獨立硬碟組合成一個邏輯單元 可以提升儲存資料的安全性,保證資料不損壞 Disk array: 多顆硬碟,以提升性能跟穩定性 Data striping: 將資料分散儲存至數個硬碟中,並以循環輪流的方法分配 Striping unit: 將資料切割的單位,分成bit及block 目標: 1. Data striping: 將資料分散儲存至數個硬碟中,利用同時讀寫多顆硬碟提升效率 2. Redundancy(冗餘儲存): 在別的硬碟上備份多的資料,當硬碟壞掉時,可以從別的硬碟上復原資料 #### RAID Level 0 * 將資料分散儲存至不同硬碟中(至少兩個) * 不使用額外空間處理Redundancy的情況 * 最簡單的RAID * ![](https://hackmd.io/_uploads/Byaj-xc82.png) #### RAID Level 1 * 只有mirrored,沒有data striping #### RAID Level 0+1 * 將同一份資料複製一份,分別存在不同的硬碟中 * 簡單的保持Redundancy,但成本高 * 寫入速度比RAID Level 0慢(取決於較慢的那顆硬碟) * 讀取速度比RAID Level 0快(可以同時讀取) * ![](https://hackmd.io/_uploads/rkqabx58n.png) #### RAID Level 3 * 將資料以位元層級分割 * 使用額外一顆硬碟利用XOR運算紀錄資料的正確性 * 能用較少的成本保持Redundancy * Transfer rate較高 * ![](https://hackmd.io/_uploads/H140Me9In.png) #### RAID Level 2 * 類似Level 3,差別在於有數個check disk #### RAID Level 4 * 與level 3類似,只差在將資料以block層級分割 #### RAID Level 5 * 與level 4類似,只差在沒有驗證資料用的那顆硬碟,而是將工作量平均分擔至其他硬碟中 ### Disk Space Manager * 利用Bitmap記錄硬碟中那些用過了,那些還沒用過 * Buffer Pool: 在主記憶體中的暫存區域,用來節省從磁盤讀取數據的時間 * unpin: 告訴系統這塊Buffer Pool中的page空間可以被挪作其他使用了 * LRU: 針對Buffer Pool中的每個page,紀錄它們的最終unpinned時間,並在需要替換時優先替換最終unpinned時間最久的 * sequential flooding: 使用LRU時,若檔案大小遠大於Buffer Pool大小,會發生不斷被逐步替患的情況,非常浪費時間 ### Record Formats 有三種儲存方式 1. 以固定長度直接存 ![](https://hackmd.io/_uploads/S1axOwq8h.png) 2. 用特殊符號區隔 ![](https://hackmd.io/_uploads/HJXG_wc8n.png) 3. 用指標指向對應的位置 ![](https://hackmd.io/_uploads/rJ2mOv9Ln.png) ### File Organizations 分成三種 1. Heap (random order) files: 適用於須掃過所有資料的查詢 2. Sorted files: 適用於只需知道某一區間資料的查詢 3. Indexes: 透過tree,hash來快速查詢 ### Index Classification * Search key 不須滿足unique的條件,故不等於key * data entry以"*"表示 * 比較 * primary index: 包含primary key的index * secondary index: 不包含primary key的index * 比較 * Cluster index: 若data record的順序接近或相等於此data之index順序,則稱為Cluster index * unCluster index: 反之 (重要) cluster(sparse): index數量比資料少,通常較為昂貴 uncluster(must be dense): index必定對到一筆資料 ![](https://hackmd.io/_uploads/r1YrRvcUh.png =70%x) ## 第十二章 (考一題) Transaction: 使用者執行一次程式(即使用者的quary) 可能同時會有許多使用者同時要求執行程式 目的: 1. 讓系統一次執行更多Transaction(system throughput: 每單位時間執行的Transaction數量) 2. 讓處理一次Transaction速度加快(Response Time) ### 解決方法: Concurrent execution -> 並行執行 讓多個使用者同時存取database,但對於每個使用者而言,又像只有他一個人在操作database 此時transaction可以被視作"a sequence of operation"(到commit或abort為止) operation 可以為: 1. reading: R(A) 2. writing: w(A) 3. commit: 4. abort: 且transaction須滿足以下特性(ACID): 1. Atomicity: * 在所有動作都順利做完後要commit * 在動作未全做完時可以abort(中止) * **commit時,所有的變動都被寫入資料庫中** * **abort時,所有的變動都不寫入資料庫中** * 可以透過log檔回復 2. Consistency(使用者須負責): * 在完成Transaction前後,資料庫的consistent須維持一致 * 若系統檢查到非consistent的條件,需要進行rolls back操作 3. Isolation: * 每個由使用者送出的Transaction都可獨立的正常運作 * 並行執行Transaction的結果應與一次執行一個Transaction的結果相同 4. Durability: * 已commit的transaction,其效果將永久存在(即使系統crash) 需探討: * interleaves: 交錯執行 * handle System crash: 處理系統當機的問題 Non-serializable Schedule ![](https://hackmd.io/_uploads/HJBP6thBh.png =30%x) commit: 寫回資料庫 問題: 排程不正確 Unrecoverable Schedule ![](https://hackmd.io/_uploads/B1DAAFnSn.png =30%x) 問題:在取消quary後,沒辦法回歸原來的情況 Abort: 取消這次quary ### Schedule 設Schedule T = {T1, …. , Tn} 為Transaction的集合 並滿足以下性質: 1. 每個Transaction中的operation都只會剛好出現一次(也就是operation的個數不變) 2. 在T中,每個Transaction中的operation的出現順序,必須要跟各自在Transaction中時一樣(也就是說,改成集合後,原先在Transaction中的順序不可改變) 分成兩種: 1. schedule: 在不執行某個Transaction時,可以跑去執行其他Transaction(允許interleave actions) 2. serial schedule: 某個Transaction做完後,才去做下一個Transaction,不允許interleave actions (是標準答案,但不唯一) schedule 處理時遇到的問題 1. WR Conflict (Dirty Read) (Reading Uncommitted Data) ![](https://hackmd.io/_uploads/HJqYvXX8h.png =30%x) T1的W(A)在commit之前就被T2 R(A)了,萬一T1後來abort就完蛋了 2. RW Conflicts (Unrepeatable Read) ![](https://hackmd.io/_uploads/HyoqU7mL3.png =30%x) T1在R(A==1)後,A的值被T2修改,導致T1的Read已經不是當初讀的那個值了 4. WW Conflict (Overwriting Uncommitted Data) ![](https://hackmd.io/_uploads/Sk_HB7XIn.png =30%x) T1跟T2同時執行Write的操作,導致結果被複寫掉 ### Strict Two-Phase Locking(Strict 2PL) 為了保持Concurrency而提出的理論 Concurrency: 並行性 1. 只允許serializable,recoverable的schedule 2. committed transactions 保證不會被遺失 觀念釐清(重要): Two-Phase指的是: hold lock跟release lock的操作 "No lock is ever acquired after one has been released" lock 分成兩種: 1. Shared lock(S): 鎖住該筆資料,使其為read-only 2. Exclusive lock(X): 鎖住該筆資料,使其不能被其他transaction修改 相關規則: 1. transaction在讀該物件之前必須要取得其Shared lock,在寫之前必須要取得其Exclusive lock 2. 如果一個transaction取得該物件的Exclusive lock,則沒有其他transaction可以取得該物件的Shared lock或Exclusive lock 3. 如果一個transaction取得該物件的Shared lock,則沒有其他transaction可以取得該物件的Exclusive lock 4. 當commited 後,解除所有lock ![](https://hackmd.io/_uploads/HktMf2YUn.png =30%x) ### 2PL 不一定能完全保證serializable 概念: 新增release條件,不再等到commit或abort時才release所有的鎖 1. 當跑去鎖(Exclusive lock)其他人後 2. 當commit前 ![](https://hackmd.io/_uploads/S1LrhsYU2.png =30%x) 舉例: ![](https://hackmd.io/_uploads/H1KYh6rU3.png =30%x) 如果再W(B)時abort,回到上一次commit前的狀態後,會發現T2的R(A)讀到的是錯誤的值 ### Deadlocks 互鎖,導致無法進行下去 解決方法: 1. 預防,使其不要發生 2. 發生,接著解決 可以用"timeout"來偵測Deadlock ![](https://hackmd.io/_uploads/B1DofpHI3.png =30%x) thrashing: 有太多被鎖住或abort的transactions,導致系統崩潰