什么是冗余字段?
在設(shè)計(jì)數(shù)據(jù)庫(kù)時(shí),某一字段屬于一個(gè)表,但它又同時(shí)出現(xiàn)在另一個(gè)或多個(gè)表,且完全等同于它在其本來所屬表的意義表示,那么這個(gè)字段就是一個(gè)冗余字段。
——以上是我自己給出的定義
冗余字段的存在到底是好還是壞呢?這是一個(gè)不好說的問題??赡茉谟腥丝磥?,這是一個(gè)很蹩腳的數(shù)據(jù)庫(kù)設(shè)計(jì)。因?yàn)樵跀?shù)據(jù)庫(kù)設(shè)計(jì)領(lǐng)域,有一個(gè)被大家奉為圭臬的數(shù)據(jù)庫(kù)設(shè)計(jì)范式,這個(gè)范式理論上要求數(shù)據(jù)庫(kù)設(shè)計(jì)邏輯清晰、關(guān)系明確,比如,”用戶昵稱”字段”nickname”本來屬于表”user”,那么,表示”用戶昵稱”的字段就唯一的只應(yīng)該屬于”user”表的”nickname”字段,這樣,當(dāng)用戶要修改昵稱的時(shí)候,程序就只需要修改 user.nickname這個(gè)字段就行了,瞧,很方便。不過問題也隨之而來,我在其他數(shù)據(jù)表(如訂單orders表)里只存儲(chǔ)了用戶的ID,我要通過這個(gè)ID值得到用戶昵稱該怎么辦呢?一個(gè)普遍的解決方法是通過聯(lián)接(join),在查詢時(shí),通過id這個(gè)唯一條件聯(lián)接兩個(gè)表,從而取到用戶的昵稱。
這樣確實(shí)是沒問題,我也一直覺得這樣是最好的方案,擴(kuò)展方便,當(dāng)要更新用戶信息時(shí),程序中要修改的地方很少,但是隨著數(shù)據(jù)庫(kù)里數(shù)據(jù)不斷增加,百萬,千萬,同時(shí),用戶表的數(shù)據(jù)肯定也在不斷的增加的,它可能是十萬,百萬。這個(gè)時(shí)候,你會(huì)發(fā)現(xiàn)兩個(gè)表通過聯(lián)接來取數(shù)據(jù)就顯得相當(dāng)費(fèi)力了,可能你只需要取一個(gè)nickname這個(gè)用戶昵稱屬性,你就不得不去聯(lián)一下那個(gè)已經(jīng)幾十萬的用戶表進(jìn)行檢索,其速度可想而知了。
這個(gè)時(shí)候,你可以嘗試把nickname這個(gè)字段加到orders這個(gè)訂單表中,這樣做的好事是,當(dāng)你要通過訂單表呈現(xiàn)一個(gè)訂單列表時(shí),涉及用戶的部分可能就不需要再進(jìn)行聯(lián)接查詢了。當(dāng)然,有利就有弊,這樣做的弊端就是,當(dāng)你嘗試更新用戶信息時(shí),你必須記得用戶信息表里當(dāng)前被更新的字段中,有哪些是冗余字段,分別屬于哪些表,找到他們,然后加入到你的更新程序段中來。這個(gè)是程序中的開銷,開銷在開發(fā)人員的時(shí)間上了。至于這樣做是否值得,就得看具體情況而定了。
所以,目前要?jiǎng)?chuàng)建一個(gè)關(guān)系型數(shù)據(jù)庫(kù)設(shè)計(jì),我們有兩種選擇:
盡量遵循范式理論的規(guī)約,盡可能少的冗余字段,讓數(shù)據(jù)庫(kù)設(shè)計(jì)看起來精致、優(yōu)雅、讓人心醉。
合理的加入冗余字段這個(gè)潤(rùn)滑劑,減少join,讓數(shù)據(jù)庫(kù)執(zhí)行性能更高更快。
選擇哪一種呢?如果你是一個(gè)美學(xué)狂人,并且財(cái)大氣粗,非要使用第一種方案,也沒關(guān)系,這種方案的短板并非不可救藥的。比如,你可以增加服務(wù)器,從數(shù)據(jù)庫(kù)集群入手,進(jìn)行讀寫分離,讀的時(shí)候可以將壓力分散到不同的數(shù)據(jù)庫(kù)服務(wù)器上,這樣也可以獲得很好的性能,只是多付出了硬件成本和維護(hù)成本?;蛘?,你可以在數(shù)據(jù)庫(kù)前端架設(shè)Memcached之類的緩存服務(wù),減少讀寫數(shù)據(jù)庫(kù)的次數(shù),也
可以達(dá)到同樣的效果。問題在于你確定你需要緩存之類的東西。
當(dāng)然,如果你跟我一樣,只有一臺(tái)每月幾十元買來的vps,甚至可能是一個(gè)虛擬主機(jī),建議還是暫時(shí)壓制你的美學(xué)欲望,跟我一起選擇第二種方案吧,除非你愿意你的整個(gè)數(shù)據(jù)庫(kù)都一直只有零零星星的幾條數(shù)據(jù)
更多信息請(qǐng)查看IT技術(shù)專欄