資料庫設計的三大正規化,分散計算思想
阿新 • • 發佈:2018-12-10
資料庫設計的三大正規化
1第一正規化:做到每列不可拆分,(一列資料中不要出現可以拆分的資料)
2.第二正規化:確保一個表只做一件事情(不要讓一個表儲存的資料可以做多個事情)
3.第三正規化:在滿足正規化二時,消除表的傳遞依賴。(比如說,表A裡的資料可以通過表A的其他資料得到。產生了多餘列,應為完全可以在程式碼中得到)
資料庫設計的反三正規化
反三正規化就是在以滿足上述三個正規化的基礎上,為了滿足客戶的特殊需求,在滿足三大正規化的基礎上又加了多餘欄位,我們稱之為反三正規化。
如:客戶在一張表中有單價,數量,需要我們給一個總價 我們設立一行總價的列就是反三正規化
分散計算思想(一般都寫在service層)
如:有兩張表,一張A(總金額表),一張B(單個商品總價表),當客戶訪問資料時,客戶想要在A中看到總金額,我們這裡就需要遍歷表B的總價,再相加,最後賦值給表A,這樣的話會造成資料載入遲緩,針對這種情況,我們可以在每次修改增加刪除表B的資料時,只要操作一次就把總價格傳給表A 進行加減,實時維護資料,這樣客戶再檢視總金額是就增強了載入速度,。而這種過程就是分散計算思想。
案例:儲存 修改 新增資料時 既要修改自己的總金額,還要修改最大的表的總金額
public void saveOrUpdate(ContractProduct entity) { //1.先判斷是新增,還是修改,等於id=null為新增, if(UtilFuns.isEmpty(entity.getId())){//新增 double amount=0.0;//2.先把貨物表的總金額設為0. if(UtilFuns.isNotEmpty(entity.getPrice())&&UtilFuns.isNotEmpty(entity.getCnumber())){ //3.再在其單價和數量都是新增的情況下,,,,讓其相乘,得到貨物的總價 amount=entity.getPrice()*entity.getCnumber(); } //4.將獲得的總價賦值給貨物總價, entity.setAmount(amount); //5.通過銷售合同的ID 查到銷售合同的資料 Contract contract = contractDaoimpl.findOne(entity.getContract().getId()); //6.通過資料給總金額賦值 總金額+新的貨物總價 contract.setTotalAmount(amount+contract.getTotalAmount()); //7.儲存修改銷售合同的總金額後的資料 contractDaoimpl.save(contract); }else{ //修改 //1.獲取當前貨物的總價 Double amount = entity.getAmount(); //2.把修改後的貨物總價設為0 Double amount1=0.0; if(UtilFuns.isNotEmpty(entity.getPrice())&&UtilFuns.isNotEmpty(entity.getCnumber())){ //3.再在其單價和數量都是新增的情況下,,,,讓其相乘,得到貨物的總價 amount1=entity.getPrice()*entity.getCnumber(); } //4.判斷修改後的貨物總價與原先是否相等,是就不修改了,不是則繼續修改 if(amount1!=amount){ //5.用計算出的新的貨物總價 為貨物總價賦值 entity.setAmount(amount1); //5.通過銷售合同的ID 查到銷售合同的資料 Contract contract = contractDaoimpl.findOne(entity.getContract().getId()); //6.通過資料給總金額賦值 總金額+新的貨物總價-原來的貨物總價 contract.setTotalAmount(contract.getTotalAmount()+amount1-amount); //7.儲存修改銷售合同的總金額後的資料 contractDaoimpl.save(contract); } } //儲存貨物資料 ContractProductdao.save(entity); }
打斷設計思想:
定義:在一方的表中加入冗餘欄位,用於儲存多方的主鍵,並用指定的字元進行分隔。
應用場景:一般在一對一,一對多是使用,多對多不推薦使用
好處:當關聯層級大於4級時,最好考慮打斷設計,能夠優化查詢速度
案列:有兩張表使用的打斷設計 entity :運單表(一) ,contract :合同表(多), ContractIds :他們之間的打斷設計的欄位 ,當儲存一張表時,需要把打斷
public void saveOrUpdate(Export entity) { //UtilFuns.isEmpty(entity.getId())判斷是否為null null 為新增資料 if(UtilFuns.isEmpty(entity.getId())){//先判斷是不是新增的, //更具運單表獲取中間表ContractIds,由於是用字元拼接的這裡我們需要使用split切割下 String[] ContractIds = entity.getContractIds().split(", "); //new StringBuffer 以便存放資料 StringBuffer ab = new StringBuffer(); for (String con : ContractIds) { //更具ID查詢合同表的資料 Contract contract = contractDaoimpl.getOne(con); //用append 存放資料,並使用空格進行分隔 ab.append(contract.getContractNo()).append(" "); } exportdao.save(entity);//呼叫儲存方法 }
設計的冗餘欄位進行更新