數據庫冗余是否必要


我們在這里假設  認為遵守數據庫設計的范式,不要冗余  的為正方:
                認為設計數據庫設計需要設計一些適當冗余的為 反方:

希望大家能結合自己設計經驗,展開積極的討論:

下面是我舉的一個例子:


 比如做一個單據表,主要字段
   單號  商品編號 商品名稱 單價  數量


正方:
  單據表只能有“ 單號  商品編號   單價  數量 ”這幾個字段,
沒有“商品名稱 ”這個字段,要顯示這個信息,就需要和 “商品基本信息表” 關聯獲取;

反方:
 
如果 這里的“商品基本信息表 ”里如果有100萬條記錄,那么我每做一個單據,單據明細信息都需要通過和100萬條記錄的“商品基本信息表 ”關聯,顯然,這樣軟件運行效率肯定要受到影響。



而且 ,寫sql語句只關聯一個表總比關聯多個表更方便。

正方:
 
如果客戶在使用過程中,商品名稱發生了改變,那么那些歷史單據上的商品名稱就會跟着變化,這樣能保證數據的一致性;否則,數據在統計的時候,明明是一個商品的入庫情況,就會被當成兩個或多個,月末結算的時候就會有問題。

反方:
 1、“商品基本信息表 ”的“商品名稱”本來就不允許輕易改變。如果該商品參與了單據處理,“商品名稱”就不應該修改。
 2、如果“商品名稱”修改了,那么修改前和修改后的單據對於同一個“商品編號”本來就應該顯示不同的“商品名稱”;就像一個人,如果他在50歲以后該名字的話,那么它50歲前作的事情,我們也應該用他的原名啊。
 3、如果正方認為“商品名稱”可以修改,那么“商品編號”也可以修改嘍。但是
 你是通過“商品基本信息表 ”的“商品編號”作為關聯的。“商品編號”一旦修改,那么單據明細由於找不到以前的“商品編號”,記錄就會丟失。這不是出大亂子。
當然,你會說“商品編號”是商品信息的唯一識別;
但是,為什么不能把“商品名稱”最為唯一識別呢。
我們不防看看用戶更改“商品名稱”的原因是什么? 其實 “商品名稱” 往往是相對固定,而“商品編號”反而會因為當初的是設計不合理,而做更改;
比如,一個中學生,他本來的編號是35 ,后來學校改革。把他的編號該成 9831
他的編號變了,但是他的名字卻不會變。如果我用冗余,就不會影響該學生在學校食堂的消費歷史紀錄;

正方:
 如果按照反方的觀點,為何需要“商品編號”,不如在“商品信息表”里就有一個“商品名稱”不就完了;中學生,也不用學號,直接用姓名識別。
首先,“商品編號”或“學生學號”是有意義的。最簡單的,“商品名稱”或“學生姓名”可能重復;但是利用編號就能容易識別;
 如果用戶需要更改編號,那么我們可以在每個表里做個內部的id字段,該字段自增長,各個表需要關聯時,都是通過他們的id來關聯。
這樣即使修改了編號也無所謂。

反方:
 使用內部id的方法,會大大加大軟件的代碼編寫的復雜度。尤其是報表系統里,為了獲取某個特定的信息會寫出很復雜的sql,就算你用視圖,道理也是一樣的,因為寫視圖也很費力。而且有時復雜的視圖的錯誤隱藏的很深。
 再說,比如那個中學生從初一上到高三,突然老師那天不小心把他的學號和姓名都修改了,那么那些在食堂里消費的歷史紀錄相應的信息修改了。結果想還原都沒有辦法。
如果我們用冗余,就不存在這個問題。

+++++++++++++++++++++++++++++++++++++++++++++++

數據庫冗余:存儲兩倍數據,冗余可以使系統速度更快。(減少聯查)

個人理解:

在設計數據庫時,某一字段屬於一個表,但它又同時出現在另一個或多個表,且完全等同於它在其本來所屬表的意義表示,那么這個字段就是一個冗余字段。

至於冗余字段的存在到底是好還是壞呢?

這是一個不好說的問題。可能在有人看來,這是一個很蹩腳的數據庫設計。因為在數據庫設計領域,有一個被大家奉為圭臬的數據庫設計范式,這個范式理論上要求數據庫設計邏輯清晰、關系明確。

比如,”用戶昵稱”字段”nickname”本來屬於表”user”,那么,表示”用戶昵稱”的字段就唯一的只應該屬於”user”表的”nickname”字段,這樣,當用戶要修改昵稱的時候,程序就只需要修改 user.nickname這個字段就行了,瞧,很方便。不過問題也隨之而來,我在其他數據表(如訂單orders表)里只存儲了用戶的ID,我要通過這個ID值得到用戶昵稱該怎么辦呢?一個普遍的解決方法是通過聯接(join),在查詢時,通過id這個唯一條件聯接兩個表,從而取到用戶的昵稱。

這樣確實是沒問題,我也一直覺得這樣是最好的方案,擴展方便,當要更新用戶信息時,程序中要修改的地方很少,但是隨着數據庫里數據不斷增加,百萬,千萬,同時,用戶表的數據肯定也在不斷的增加的,它可能是十萬,百萬。這個時候,你會發現兩個表通過聯接來取數據就顯得相當費力了,可能你只需要取一個nickname這個用戶昵稱屬性,你就不得不去聯一下那個已經幾十萬的用戶表進行檢索,其速度可想而知了。

這個時候,你可以嘗試把nickname這個字段加到orders這個訂單表中,這樣做的好事是,當你要通過訂單表呈現一個訂單列表時,涉及用戶的部分可能就不需要再進行聯接查詢了。當然,有利就有弊,這樣做的弊端就是,當你嘗試更新用戶信息時,你必須記得用戶信息表里當前被更新的字段中,有哪些是冗余字段,分別屬於哪些表,找到他們,然后加入到你的更新程序段中來。這個是程序中的開銷,開銷在開發人員的時間上了。至於這樣做是否值得,就得看具體情況而定了。

所以,目前要創建一個關系型數據庫設計,我們有兩種選擇:

1,盡量遵循范式理論的規約,盡可能少的冗余字段,讓數據庫設計看起來精致、優雅、讓人心醉。

2,合理的加入冗余字段這個潤滑劑,減少join,讓數據庫執行性能更高更快。

選擇哪一種呢?如果你是一個美學狂人,並且財大氣粗,非要使用第一種方案,也沒關系,這種方案的短板並非不可救葯的。比如,你可以增加服務器,從數據庫集群入手,進行讀寫分離,讀的時候可以將壓力分散到不同的數據庫服務器上,這樣也可以獲得很好的性能,只是多付出了硬件成本和維護成本。或者,你可以在數據庫前端架設Memcached之類的緩存服務,減少讀寫數據庫的次數,也可以達到同樣的效果。問題在於你確定你需要緩存之類的東西。

如果做不到上面的只能選擇第二種了,當涉及到修改的時候就需要將所有相關的數據進行修改了。

空間換取時間,到底值不值得,看業務需求與取舍了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM