自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何不改表結(jié)構(gòu)動態(tài)擴展字段?

開發(fā) 后端 MySQL
筆者的動態(tài)字段擴展解決方案主要針對 Mysql 5.7.8 以下版本,在 Mysql 5.7.8 已經(jīng)新增 JSON Data Type,同樣適用該方案,而且情況變得更加簡單。

[[408268]]

 痛點

軟件行業(yè)唯一不變的就是變化,比如功能上線之后,客戶或 PM 需要對已有的功能增加一些合理的需求,完成這些工作必須通過添加字段解決,或者某些功能的實現(xiàn)需要通過增加字段來降低實現(xiàn)的復雜性等等。

這些問題都會改動線上的數(shù)據(jù)庫表結(jié)構(gòu),一旦改動就會導致鎖表,會使所有的寫入操作一直等待,直到表鎖關(guān)閉,特別是對于數(shù)據(jù)量大的熱點表,添加一個字段可能會因為鎖表時間過長而導致部分請求超時,這可能會對企業(yè)間接造成經(jīng)濟上的損失。

解決方案

增加 json 格式的擴展字段。

下面配合一些代碼來描述這個解決方案,讀者便于去理解。另外,MySQL 系列面試題和答案全部整理好了,微信搜索Java技術(shù)棧,在后臺發(fā)送:面試,可以在線閱讀。

mysql 數(shù)據(jù)庫腳本: 

  1. DROP TABLE IF EXISTS `cs_dustbin`;  
  2. CREATE TABLE IF NOT EXISTS `cs_dustbin` (  
  3.   `id` VARCHAR(45) NOT NULL COMMENT '主鍵自增id',  
  4.   `rfid_no` VARCHAR(20) NOT NULL COMMENT 'rfid 卡號',  
  5.   `state` INT(1) NOT NULL COMMENT '垃圾桶狀態(tài):0:已注銷;1:未使用;2:待使用;3:已使用(綁定收集點);',  
  6.   `user_id` INT NOT NULL COMMENT '登記人,負責錄入垃圾桶的人',  
  7.   `type` INT(1) NOT NULL DEFAULT 1 COMMENT '垃圾桶類型:1:餐廚垃圾桶',  
  8.   `street_code` INT(11) DEFAULT NULL COMMENT '所在鎮(zhèn)街 code,根據(jù)狀態(tài),這里的含義可能是領用鎮(zhèn)街、退還鎮(zhèn)街。',  
  9.   `create_time` DATETIME NOT NULL DEFAULT now() COMMENT '創(chuàng)建時間',  
  10.   `update_time` DATETIME NOT NULL DEFAULT now() COMMENT '更新時間',  
  11.   `ext` VARCHAR(1000) NOT NULL DEFAULT '{}' COMMENT '擴展字段',  
  12.   ...  
  13.   PRIMARY KEY (`id`))  
  14. ENGINE = InnoDB  
  15. COMMENT = '垃圾桶表'

Java 代碼: 

  1. import com.alibaba.fastjson.JSON;  
  2. import lombok.Data;  
  3. import javax.validation.constraints.NotNull;  
  4. import java.util.Date;  
  5. import java.util.List;  
  6. /**  
  7.  * 垃圾桶實體  
  8.  * Created by Blink on 6/28/2018 AD.  
  9.  *  
  10.  * @author Blink  
  11.  */  
  12. @Data  
  13. public class Dustbin {  
  14.     private String id;  
  15.     /**  
  16.      * rfid 卡號  
  17.      */  
  18.     @NotNull  
  19.     private String rfidNo;  
  20.     /**  
  21.      * 垃圾桶狀態(tài):0:已注銷;1:未使用;2:待使用;3:已使用(綁定收集點);  
  22.      * 對應 Dustbin.StateEnum 類  
  23.      */  
  24.     @NotNull  
  25.     private Integer state;  
  26.     /**  
  27.      * 錄入垃圾桶的人員id  
  28.      */  
  29.     @NotNull  
  30.     private Long userId;  
  31.     /**  
  32.      * 垃圾桶類型:1:餐廚垃圾桶  
  33.      * DefaultValue: 1  
  34.      */  
  35.     @NotNull  
  36.     private Integer type; 
  37.     /**  
  38.      * 所在鎮(zhèn)街 code  
  39.      * 根據(jù)狀態(tài),這里的含義可能是領用鎮(zhèn)街、退還鎮(zhèn)街  
  40.      */  
  41.     private Integer streetCode;  
  42.     /**  
  43.      * 創(chuàng)建時間  
  44.      * defaultValue : now()  
  45.      */  
  46.     @NotNull  
  47.     private Date createTime;  
  48.     /**  
  49.      * 更新時間  
  50.      */  
  51.     @NotNull  
  52.     private Date updateTime;  
  53.     /**  
  54.      * 擴展字段,詳細數(shù)據(jù)查看 DustbinExt.java  
  55.      * DefaultValue: {}  
  56.      */  
  57.     private String ext;  
  58.     ...  
  59.     public DustbinExt getExtObject() {  
  60.         return JSON.parseObject(this.getExt(), DustbinExt.class);  
  61.     }  
  62.     public void setExtObject(DustbinExt ext) {  
  63.         this.ext = JSON.toJSONString(ext);  
  64.     }  
  65.     /**  
  66.      * 垃圾桶擴展屬性  
  67.      * Created by Blink on 6/28/2018 AD. 
  68.      *  
  69.      * @author Blink  
  70.      */  
  71.     @Data  
  72.     public static class DustbinExt {  
  73.         /**  
  74.          * 所在鎮(zhèn)街  
  75.          * 根據(jù)狀態(tài),這里的含義可能是領用鎮(zhèn)街、退還鎮(zhèn)街、綁定的鎮(zhèn)街  
  76.          */  
  77.         private String street;  
  78.         /**  
  79.          * 客戶(收集點)id,綁定收集點的時候需要填入  
  80.          * 根據(jù)目前的需求(2018-06-29),當收集點解綁的時候  
  81.          * 需要保存垃圾桶最新綁定收集點名稱,所以在解綁垃圾桶的時候不會把這個信息刪掉  
  82.          * 只有當綁定收集點的時候才把他覆蓋  
  83.          */  
  84.         private Long customerId;  
  85.         /**  
  86.          * 客戶(收集點)名稱,綁定收集點的時候需要填入  
  87.          * 根據(jù)目前的需求(2018-06-29),當收集點解綁的時候  
  88.          * 需要保存垃圾桶最新綁定收集點名稱,所以在解綁垃圾桶的時候不會把這個信息刪掉  
  89.          * 只有當綁定收集點的時候才把他覆蓋  
  90.          */  
  91.         private String customer;   
  92.         /**  
  93.          * 損壞部位  
  94.          * 1:桶蓋;2:桶口;3:桶身;4:桶軸;5:桶底;6:桶輪;  
  95.          * 對應 DustbinDamagePartEnum 類  
  96.          */  
  97.         private List<Integer> parts;  
  98.     }  
  99.     ... 
  100.  

mysql 腳本可以看到擴展字段的信息:

  1. ext VARCHAR(1000) NOT NULL DEFAULT '{}' COMMENT '擴展字段' 

可以看到這么一段 Java 代碼: 

  1. ...  
  2. /**  
  3.  * 擴展字段,詳細字段查看 DustbinExt 類  
  4.  * DefaultValue: {}  
  5.  */  
  6. private String ext;  
  7. public DustbinExt getExtObject() {  
  8.     return JSON.parseObject(this.getExt(), DustbinExt.class);  
  9.  
  10. public void setExtObject(DustbinExt ext) {  
  11.     this.ext = JSON.toJSONString(ext);  
  12.  
  13. ... 

可以看到 ext 字段就是用來存儲 json 格式的數(shù)據(jù),它可以動態(tài)地增加任何字段,甚至是對象,不需要通過 DDL(Data Definition Language) 去創(chuàng)建字段,非常適合用來解決上面提到的問題。

Java 代碼在這里起到輔助性作用,通過定義一個內(nèi)部類來管理擴展字段的屬性,方便我們了解和管理擴展字段,提高代碼的可讀性和可維護性,java 這種方式也是筆者總結(jié)出來的較為優(yōu)雅的做法(個人觀點)。

局限性

有經(jīng)驗的讀者可能會提出,ext 字段在 Mysql 5.7.8 以下版本無法對擴展字段中的某一個或一部分字段建立索引,因為 Mysql 5.7.8 版本以下不支持(Mysql 5.7.8 支持為 Json Data Type 建立索引)。MySQL數(shù)據(jù)庫開發(fā)的 36 條軍規(guī)!

沒錯,這是這個解決方案的一個局限性,在 Mysql 5.7.8 以下版本,我的建議是, ext 擴展字段不要存儲熱點數(shù)據(jù),只存儲非熱點數(shù)據(jù),這樣就可以避免查詢操作,降低維護 ext 字段帶來的成本和風險,那如何識別新增字段是不是熱點數(shù)據(jù)呢?

這個需要結(jié)合實際業(yè)務需求來判斷,也可以詢問對業(yè)務和技術(shù)更有經(jīng)驗的同事,便于讀者更快得出結(jié)論。

終極版解決方案

在一些極端的情況下,變化可能來得太快,而我們要的是減少變化帶來的成本和風險,所以在表設計之初可以根據(jù)自身經(jīng)驗,或者找更有經(jīng)驗的人尋求幫助,預估一下需要預留多少個備用字段,再配合擴展字段,基本上可以把改變(添加字段)表結(jié)構(gòu)的次數(shù)降至一個非常少的次數(shù)。

總結(jié)

在特殊情況下,通過擴展字段 + 預留字段基本上可以做到動態(tài)擴展字段,又不會影響為熱點數(shù)據(jù)建立索引的情況,這樣我們得到了一個非常靈活的表結(jié)構(gòu),便于我們應對未來的變化,但是請注意,要維護好我們的實體,包括里面的每一個字段,敬畏每一行代碼。

最后,關(guān)注公眾號Java技術(shù)棧,在后臺回復:面試,可以獲取我整理的 MySQL 系列面試題和答案,非常齊全。 

 

責任編輯:龐桂玉 來源: Java技術(shù)棧
相關(guān)推薦

2010-09-16 15:56:15

SQL Server表

2010-10-13 10:03:08

MySQL修改表結(jié)構(gòu)

2021-01-04 08:24:44

Class字段表方法表

2015-08-18 13:25:12

PaaS服務架構(gòu)動態(tài)擴展

2012-06-14 10:14:46

ibmdw

2020-08-07 07:58:24

Oracle框架數(shù)據(jù)庫

2010-06-01 09:20:45

jQuery

2023-03-21 08:41:09

結(jié)構(gòu)設計數(shù)據(jù)庫高性能

2011-01-20 17:44:25

2010-03-17 10:17:37

Java

2024-07-01 12:13:44

2015-09-24 08:54:36

java動態(tài)代理

2015-09-24 08:55:14

Java動態(tài)代理擴展

2010-09-28 14:52:37

SQL表結(jié)構(gòu)

2022-09-02 15:38:06

KubernetesYAML

2024-06-20 08:26:01

JPA公共字段

2010-04-21 09:26:54

Java動態(tài)代理

2011-04-07 14:04:28

SQL動態(tài)交叉表

2024-12-05 08:16:32

2024-06-14 16:24:42

點贊
收藏

51CTO技術(shù)棧公眾號