key+value實現動態欄位的儲存設計
一般我們在儲存例如使用者資訊的時候,使用者資訊的各屬性是固定的,這時我們可以通過如下方式設計表: user(user_id, name, age, sex)
但是,如果某天呢,產品說使用者資訊需要加幾個屬性:height、weight。
此時,如果表沒什麼資料當然是想加直接加上就行了,程式碼中跟著新增幾個欄位就OK了。但是如果資料量和併發量特別大怎麼辦?
alter table add column是不行的,因為鎖表時間會很長。
這裡說一種key+value的儲存方式實現方法,此時表設計為: user(user_id, key, value)
表裡資料樣式為:
user_id | key | value |
---|---|---|
1 | name | 張三 |
1 | age | 50 |
1 | sex | 男 |
1 | height | 170 |
1 | weight | 120 |
2 | name | 小胖呆 |
2 | age | 30 |
2 | sex | 男 |
這種將一行儲存的資料拆成在一列裡面儲存的方式就是key+value動態欄位儲存。
key+value儲存方式優缺點
優點: 可以隨時動態擴充套件欄位屬性
缺點: 1) key值有大量冗餘。建議key短一些 2) 行數會增加很多 3)索引設計可能比較麻煩
key+value儲存方式使用場景
服務端,wordpress,EAV,配置,統計項、APP或者PC客戶端、儲存個人資訊等等
key+value應用場景之——自定義頁面功能設計
在有些系統中,可能會有這樣一個需求:使用者可以自定義某個頁面的表單個數及樣式。至於樣式的自定義怎麼實現,不是這裡要說的,這裡只說說關於表單個數的自定義實現。
在這種需求裡,你不會知道使用者到底會定義多個表單,這樣你就不能在一張表裡固定欄位的個數。這時就可以利用key+value方式實現。
我們模擬一個業務場景:系統中有一個作物資訊採集頁面,每個種植公司可根據自己的需求設定不同的表單;例如公司A希望該頁面能收集:作物品種、種植地塊、作物高度、有無草害、有無蟲害;而公司B則希望收集:作物品種、種植地塊、當時田間溫度、採集時間。
先設計出如下幾張表(只有關鍵的欄位):
模(mu)板表:model(id, model_name, company_id) 欄位描述分別是:主鍵、模板名稱、公司ID
模板部件表:model_parts(id, key_name, label, required, type, model_id) 欄位描述分別是:主鍵、表單name,表單裡的label、是否必填、型別(數字或字串)、模板ID
作物資訊採集表: crop_info(id, key, value, company_id, model_id) 欄位描述分別是:主鍵、表單name,表單值,公司ID,模板ID
接著給各表新增資料:
模板表(model)需要管理員新增資料:
id | model_name | company_id |
---|---|---|
1 | 玉米資料採集模板 | 100 |
2 | 土豆資料採集模板 | 101 |
部件表(model_parts):在作物採集頁面顯示的都是來源於部件表的資料。
id | key_name | label | required(1:必填,0:非必填) | type(1:數字,2:字串) | model_id |
---|---|---|---|---|---|
1 | category | 作物品種 | 1 | 2 | 1 |
2 | land_name | 種植地塊 | 1 | 2 | 1 |
3 | height | 作物高度 | 1 | 1 | 1 |
4 | grass | 有無草害 | 1 | 1 | 1 |
5 | insect | 有無蟲害 | 1 | 1 | 1 |
6 | category | 作物品種 | 1 | 2 | 2 |
7 | land_name | 種植地塊 | 1 | 2 | 2 |
8 | temperatrue | 田間溫度 | 1 | 2 | 2 |
9 | collect_time | 採集時間 | 1 | 2 | 2 |
作物採集表: crop_info
id | key | value | company_id | model_id |
---|---|---|---|---|
1 | category | 玉米 | 100 | 1 |
2 | land_name | 地塊一 | 100 | 1 |
3 | height | 120 cm | 100 | 1 |
4 | grass | 有 | 100 | 1 |
5 | insect | 無 | 100 | 1 |
6 | category | 土豆 | 101 | 2 |
7 | land_name | 江家灣地塊 | 101 | 2 |
1 | temperatrue | 36.5 | 101 | 2 |
1 | collect_time | 2018-10-10 | 101 | 2 |
以上所有遵循正規的表設計,這裡只是提供一個思路
作物採集表就完全體現了key+value動態儲存的思想。