數據表的物理實現
衝突的目標(最核心的特點:讀寫衝突)
- 併發用戶數很大的系統
- 儘量以緊湊的方式存儲數據(有助於查詢)
- 儘量將數據分散存儲(有助於存儲,併發寫入)
- 沒有併發的修改密集型(change-heavy)
- 查詢數據要快
- 數據更新也要快
- 這是一個衝突的目標
- DBMS所處理的基本單元(頁、塊)通常不可分割
- 在系統工程師眼裏一切都很完美的時候,也可能存在一定的問題
- 如果想要優化,就必須得處理數據庫引擎所訪問的頁和塊的數量。
- 努力的方向:
- 努力使每一頁的數據的密度更高(將一個檢索所處理的結果儘可能的聚集在一起)
數據密集的時候方便修改,數據分散的時候方便修改、併發
在關係型數據庫之中,不可能有一個技術同時對讀和寫都友好
頁模式
- 鏈表模式的目的是優化查詢效率
- 頁不僅可以通過“目錄頁”查找到在哪,還有前後的指針指向前一張、後一張的頁(將前後的頁、塊像鏈表一樣聯繫在一起),方便做掃描/查找
- 目錄頁本質也是頁,普通頁中存的數據是項目數據,而目錄頁中存的數據是普通頁的地址。
- 對於DBMS引擎來說,會自動爲每一個數據塊預留一小塊空間
- 大約每一頁只會使用大約70%的空間;超過這個空間的閥值的時候DBMS就默認這個塊(頁)已經存滿了。
把索引當成數據倉庫(IOT)
- 當索引中增加額外的字段(一個或多個,它們本身與實際搜索條件無關,但包含查詢所需要的數據),能夠提高某個頻繁運行的查詢的速度。
- 儘量在索引中多存儲數據的極限是?–允許在逐漸索引中存儲表中所有數據,表就是索引。
- Oracle:“索引組織表(IOT)”:所有的數據都存儲在索引中,甚至不需要基本表。IOT本身是一個順序文件。
- 對數據的寬表插入和索引是長字符串的情形非常不友好。
- Oracle:“索引組織表(IOT)”:所有的數據都存儲在索引中,甚至不需要基本表。IOT本身是一個順序文件。
記錄強制排序(IOT的優缺點)
-
IOT最大的優點:記錄是排序的,查詢效率非常的高
- 所有基於時間進行的排序,這樣做會很好(使用聚簇索引,就是以某一個屬性來決定某條記錄在表中的順序)
-
使用聚簇索引之後,插入效率降低一倍;然而查詢效率大幅提高
-
表變成了樹狀結構
-
“層次型數據庫”式的數據組織結構
數據自動分組
分區
- 是一種數據分組方式
- 是最常用的提高併發性和並行性的一種策略
- 從而增強系統架構的可伸縮性
- 思想:
- 將一個大型的表,在物理上分成多個小型的表,但是藉助於DBMS引擎,邏輯上依舊是一張完整的表
分區技術最早是用來進行高效管理的技術。
從前數據庫拷貝是很慢的。比如一個數據庫整體拷貝下來需要60min,如果在第59min的節點上出現了故障,它會直接回滾;前59min的工作可能就直接浪費掉了;
假如你把這個數據庫分成10個區,拷貝操作就變成了對這10個區的順序拷貝;每個區拷貝起來也就6分鐘;如果中途再出現異常,頂多也就浪費6分鐘,就從斷了的節點重新開始操作就行了
數據庫管理的效率就大幅提升了。
循環分區(從物理角度出發的數據分區,不考慮數據邏輯)
-
一般把分區設置在各個磁盤的存儲區域中間,甚至一個分區就是一個設備。這樣一個表可能會存儲在一個或多個分區上。插入數據的時候,數據會按照某種方式循環加載在各個分區上,以保障插入操作的磁盤IO操作的平衡。
-
循環分區:不受數據影響的內部機制
-
分區定義爲各個磁盤的存儲區域
-
可以看作是隨意散佈數據的機制(不是根據邏輯數據的相關性來存儲數據的)
-
保持更改帶來的磁盤IO操作的平衡
- 循環分區對於併發的隨機存儲很有幫助(數據越分散,越適合併發工作)
數據驅動分區(根數據本身的邏輯有密切的聯繫)
社交網絡數據的分區:按照時間來分區
將近3個月內的數據組織成一張表,6個月前-3個月前的數據組織成一張表,以此類推……
那麼如果需要讀取近一年的數據,只要連續union4張表就行了
-
核心在於“分區鍵(partitioned key)”,也就是分區的時候根據一個或者多個字段的值來決定這條數據應該被分在哪個分區之中。這樣導致,不同的分區跟記錄中間的一條或者多條數據就產生了強的/弱的聯繫。
-
根據一個或者多個字段中的值來定義分區
- 一般叫分區視圖(partitioned view),而Mysql稱爲(merge table)
-
分區的實現方式
-
哈希分區
- 對分區鍵進行hash運算,根據運算結果進行分區
- 能夠保證根據分區鍵可以快速的找到記錄,但是對於範圍的檢索沒有任何幫助;更接近於循環分區,只是爲了做負載均衡使用的,可以提高併發能力
- 以數據值本身爲分區的基礎
-
範圍分區
- 根據連續數據的範圍進行分區
- 非常適合處理歷史數據
-
列表分區
- 是一種最具手工風格的分區方案,適合定製某種特殊的解決方案
- 比如一張表有10個字段,我們把每2個字段放在一個分區,這樣這張表就分成了5個分區。這就叫列表分區
- 如果一個表很大,我們的查詢通常只涉及某幾個字段;或者是某幾個字段通常一起查詢,這時候就能使用列表分區
- 有個問題:會造成主鍵的冗餘存儲,浪費空間(每一個分區都要存儲一次主鍵,保持數據的一致性、完整性)
-
分區是可以嵌套的(套娃分區,父級分區使用A方案,子級分區使用B方案)
-
分區利弊
- 沒有銀彈。根據具體的查詢/操作場景,有利有弊。
- 針對主要矛盾進行技術選型。
分區與數據分佈
- 表非常大,且希望避免併發寫入數據的衝突未必一定要用分區。
- 如果希望使用分區,那麼當數據按分區鍵均勻分佈的時候,分區的收益是最大的。
數據分區的最佳方法
- 整體改善業務處理的操作,纔是選擇非缺省的存儲選項的目標,纔是重中之重。
- 更新分區鍵會引起移動數據,似乎應該避免這麼做
- 例如實現服務隊列
- 按請求類型分區:進行的等待降低
- 按照狀態分區:輪詢的開銷降低
- 取決於:服務器進程的數量、輪詢頻率、數據的相對流量、各類型請求的處理時間、已經完成請求的移除頻率
- 對錶分區有很多方法,顯而易見的分區未必有效,一定要整體考慮
小結
- 除了堆文件之外的任何存儲方法,都會帶來複雜性
- 除了單庫單表之外任何的存儲方法,都會帶來複雜性
- 選錯存儲方式會帶來大幅度的性能降低。
- 設計非常重要,但是任何設計都有時效性
- 看重測試。