物理結構的設計,也即是設計數據在磁盤上的存儲,需要考慮:安全(容災)、性能(IO競爭少)、服務器資源利用率高。
通常當前數據庫只使用一份ONLINE的數據源,至於分佈式存儲已經上升到服務器架構的設計,這裏不作討論。以下僅簡單描述非分佈式存儲的情況,主要從磁盤、文件、表數據三方面來說。
一、磁盤
RAID0提供了最好的讀寫性能,但RAID0沒有提供冗餘恢復策略,所以很少單獨全用。通常,使用RAID10或RAID5來實現磁盤數據的存儲與容災。
隨着磁盤上數據量的提升,RAID5的讀寫性能會明顯低於RAID10,RAID5至少需要3塊磁盤,RAID10至少需要4塊磁盤,RAID5在同樣提供數據容災的情況下,更能節省成本,但如果成本不在考慮範圍內,當然是性能優先,使用RAID10。
二、文件
2.1、文件組(表空間)
在SQL SERVER中叫文件組,在ORACLE中叫表空間,它們都是對數據文件的邏輯分組。使用文件組的目的如下:
(1)性能
文件組中的文件放在不同磁盤上,是否可以提高讀寫的效率?在使用RAID1或RAID5的情況下,這種效率的提升已經幾乎可以忽略,因爲數據本身已經被分散寫到RAID上的各塊磁盤上;
(2)管理
目前使用文件組的目的,大都出於管理。
a)在磁盤空間不足的情況下,可以使用多個小空間的磁盤,同時,也可爲數據庫擴展新的磁盤空間;
b)文件組的備份/還原,只讀/讀寫,離線/在線等數據庫管理與維護;
SQL SERVER中文件組與文件的關係如下圖:
2.2、文件
(1)如果文件組中的文件被限制大小,文件填滿了會不會自動新建一個文件?
不會,那麼此時數據庫會報出空間不足的錯誤,所以在定義文件時,要麼指定其大小無限增長(直到填滿磁盤空間),要麼定期檢查文件空閒空間的大小,以手動擴展。
(2)文件組中文件是一個個寫入還是各個文件同時都在增大?
SQL SERVER中是文件組中各個文件同時寫入,ORACLE中是寫滿一個再寫下一個。
三、表數據
3.1、堆表和索引組織表
使用堆表還是索引組織表,取決於對DML效率的要求。
(1)堆表在DML時沒有聚集索引的維護成本,在非明確指定的情況下,ORACLE中默認使用堆表;
(2)對於主鍵的單值或範圍查找,尤其是範圍查找,索引組織表效率更高,因爲省去了bookmark lookup的成本,在非明確指定的情況下,SQL SERVER中默認使用索引組織表。
關於堆表和索引組織表的設計,詳見《SQL Server 查詢優化》系列。
3.2、表數據分割
數據分割的方式,通常可分爲以下兩種:
3.2.1、水平分割
出於讀寫性能的考慮,將一個大表,拆分爲若干個小的單元,應用程序根據每個單元的入口規則,映射到相應的單元,只處理所需訪問的單元中的數據,以提高數據讀寫的效率。
水平分割針對表中數據行進行分割,可採用以下方式:
(1)分表
在還沒出現分區的概念時,對於大表,通常採用分表的方式來實現數據的水平分割。
按照一定的規則將數據分別存入不同名稱的表中:
a)最常見的就是按日期、時間來分表,比如:將每月的訂單放到當前月的訂單表中,orders_201001、orders_201002、orders_201003……依次類推;
b)也可以根據編號規則來分表,比如將尾數:將訂單尾數爲1的訂單放到一個表中,orders_1、orders_2、orders_3……依次類推;
(2)表分區
a)SQL SERVER 2005以前的版本中,出現過分區視圖,算是它在分區表出現前的一個替代品,有本地分區視圖和分佈式分區視圖兩種。分佈式分區視圖的概念,倒是有現在分佈式存儲的味道,但由於受網絡因素影響較大,未被廣泛使用。
b)對於本地化的表分區,目前多采用分區表,結構如下圖:
3.2.2、垂直分割
垂直分割針對表中列進行分割。
如果表中列非常多,從而導致一行數據所佔用的存儲空間非常大時,可以考慮進行垂直分割,比如:將一個表拆成主表和從表,主表中存放訪問最頻繁的列,從表中存放訪問較少的列,從而提高數據讀取的效率。
通常不建議使用垂直分區,如果主從表都變得很大,在需要進行主從表關聯時,成本也是相當高的,可能會影響性能。
3.3、簇
簇(CLUSTER),這是ORACLE裏的一個概念,將多個表中相同的字段存放到一起,稱爲簇,即聚集的意思,這裏需要和聚集索引的概念區分開來。放到一起的好處如下:
(1)節省存儲空間,相同數據只需要存一份;
(2)提高多表關聯的速度;