現今網站不跟資料庫扯上關係的實在少之又少,而資料庫本身的管理及設計也是常造成效能瓶頸的主因,相關主題實在太多,此篇幅不足涵蓋全數,本篇將針對資料庫設計時在實務面上較常遇到的議題進行探討。

正規化與反正規化設計

就資料庫設計而言,資料正規化在教科書中亦視為重要課題,不外乎在強調資料重複性及一致性的維護;相對地,當正規化得愈徹底,未來資料查詢時需要進行join的頻率就會很高。但就實務而言,過度的正規化反倒是造成效能瓶頸的主因,尤其當個別資料表格內含龐大資料量時,多項資料表格進行join時,所付出的系統資源成本是相當可觀的。

資料正規化固然能解決資料面重複不一致的問題,以達到有效規畫及善用儲存空間的基本精神,但就資料存取的效能考量而言,有時適度的重複資料,反倒能減少因為頻繁join所需付出的系統成本。而重複資料可以透過其他機制來控制,或是由定期的資料維護檢核機制來處理,以磁碟空間換取時間。所以「反正規化」的做法是可接受的,尤其是在系統效能要求較高的環境下。

反正規化的想法也可以結合到非資料庫的儲存媒介,因為不見得網頁上所要呈現的所有內容都必須儲存在資料庫中,適時將部分的資料內容以檔案的方式來配置存放,亦對執行效能有加分效果。尤其是針對內容長度較大的資料,像是購物網站的商品說明內容,就可以透過此種方式設計實作。

資料庫與檔案的設計決策

若你所負責的網站系統是對Internet上的所有使用者提供服務,它的特性在於你永遠無法精準預估可能發生的流量有多大。若將所有網站上所需的資料都以資料庫的方式存取,流量低時不會有什麼問題,而流量高時就有明顯差異了。

就儲存媒介的資料存取效能而言,記憶體優於檔案,檔案勝於資料庫。這些儲存媒介的單位成本與使用時機也都不同,所以若你所規畫的網站系統是對外服務,在同一時間所造訪的人數是無法預估的,而偶爾會有尖峰時段。你可以觀察一些知名高流量的網站,會發現站上大多數的頁面會以靜態頁的方式來處理,也是想解決尖峰流量發生時不會因為系統資源的過度耗用而造成網站效能不佳。

透過以下幾點使用原則來評估,可以協助你資料設計時,去評估使用哪一種儲存媒介較佳:

1. 資料內容被前端使用的方式,是唯讀或是會被異動。若資料內容主要是做為網頁唯讀呈現(像是新聞內容、部落格網站、企業門戶網站等),僅允許由管理後臺進行資料更新,我建議這些內容可以利用檔案的方式來儲存。

2. 資料被異動的來源及頻率。異動的頻率也可視為決定儲存方式的考量點,像是企業網站的服務內容及產品訊息,異動頻率不高,就可以透過簡單的檔案方式來做為主要儲存方式;然而異動資料的來源單純,而非開放式供所有使用者可異動,則可以透過資料流程的設計來控制異動點。

3. 資料未來被管理及操作的方式。所有資料都放在資料庫,主要是方便未來進行資料分析所使用,但實務上的規畫並不會對線上資料庫進行較複雜的報表產出或資料分析,一般都是採用資料庫複寫機制(Replication)抄寫到別的資料庫中,或是將部分資料轉入到另外的系統進行後置報表產生作業,這麼做,主要在於避免線上直接查詢所造成的效能影響。

舉個實例,就內容網站而言,管理者可以透過後臺的管理介面,定義整個網站的內容分類架構,這些資料內容可以儲存到資料庫中,但前臺的網頁呈現,我建議另外產生檔案方式來提供瀏覽網頁的呈現,而不由前臺的網頁程式直接存取資料庫。

另外像是許多網站提供的個人化網頁內容,其內容呈現需要透過資料庫的運算統計得出的數字(像是未讀取的訊息數、未支付的訂單數、累積紅利點數等),在設計上應避免直接即時查詢資料庫運算得出。我建議以檔案儲存這些運算好的結果,來供前臺的快速呈現,而這些檔案內容被異動的時間點,則可以考慮定期批次整體更新,或是當資料庫異動時一併更新的方式,來達到資料異動。

資料表索引建立原則

索引的建立,不外乎是為了加速資料查詢以及排序時處理的效率,而原則主要依據查詢命令所要求的條件,將需要的查詢或排序欄位列入建立索引欄位的關鍵值。而建立為索引的欄位,必須配合前端程式存取資料的行為來建立,才能適時發揮效用。

若資料表本身會發生大量INSERT作業,則過多索引的建立反倒造成較高的效能成本,而且相關資料表必須定期維護,所以要評估資料表存取的方式來建立適當的索引,才不致於造成反效果。而資料表的Join關聯欄位,也是建立索引的重要對象,尤其是被join的資料表含有較大量的資料時,對明顯提升join時比對運算的效能有利。

資料空間的有效管理

資料表在經過長時間不斷插入及刪除動作後,像是購物網站的購物車內容,對該資料表的索引結構與實體磁碟結構的排列及對應位置,會造成不一致的狀況,甚至會有部分空間未能有效運用的狀況,占用較實際資料量為高的磁碟空間,造成索引存取效能低落的現象。

若資料表的資料異動頻率甚高,資料量亦居高不下(一般而言,是同一個資料表超過十萬筆以上的資料量),索引結構的重整,便是系統日常維運時所需重視的定期維護作業。可以透過資料庫系統提供的重建索引命令(rebuild index),或是透過索引移除、再重新建立的方式進行,亦可達到重整索引的效果。

而資料表本身的空間亦會因而無法有效運用,造成空間碎塊(Defragment)。利用資料庫本身的空間壓縮(Shrink)機制,可有效整理出未使用空間以提高空間使用率,而這個動作已成為資料庫備份之前的必要程序,甚至在建立資料庫時就設定成自動壓縮,以保持資料庫的壓縮比在一定的使用水平。

資料量分散移轉作業

網站系統運作一段時間之後,部分功能可能會因為資料量的成長而發生效能上的問題,針對資料量較大的資料表,可以考慮將存取頻率較低的部分,分散到另外的資料表,以有效保持原本資料表的資料存取效能。像是購物網站前臺,若提供會員查詢近半年的訂單資料,所以在訂單主檔的資料表便只保留時間範圍內的資料,其他可移至其他資料表。

不過這是土法煉鋼法,必須自行額外觀察資料的成長量,定出合適的時間範圍區段。若你的資料庫系統支援區段資料表(partitioning table)的機制,這部分的作業就單純許多,僅需要設置該資料表即可,未來該資料表便會依設置進行實體檔案空間的分散配置,以利一定品質的存取效能。就虛擬而言,上述做法仍然是針對同一個資料表進行操作,而實體資料檔案則會依設定時的定義進行切割。好處則是應用程式不需要針對不同的資料表進行存取。

專欄作者

熱門新聞

Advertisement