如何做好表結(jié)構(gòu)設(shè)計?
前言
最近有不少前端和測試轉(zhuǎn)Go的朋友在??交流群??里聊:如何做表結(jié)構(gòu)設(shè)計?
大家關(guān)心的問題陽哥必須整理出來,希望對大家有幫助。
4個方面
設(shè)計數(shù)據(jù)庫表結(jié)構(gòu)需要考慮到以下4個方面:
- 數(shù)據(jù)庫范式:通常情況下,我們希望表的數(shù)據(jù)符合某種范式,這可以保證數(shù)據(jù)的完整性和一致性。例如,第一范式要求表的每個屬性都是原子性的,第二范式要求每個非主鍵屬性完全依賴于主鍵,第三范式要求每個非主鍵屬性不依賴于其他非主鍵屬性。
- 實體關(guān)系模型(ER模型):我們需要先根據(jù)實際情況畫出實體關(guān)系模型,然后再將其轉(zhuǎn)化為數(shù)據(jù)庫表結(jié)構(gòu)。實體關(guān)系模型通常包括實體、屬性、關(guān)系等要素,我們需要將它們轉(zhuǎn)化為表的形式。
- 數(shù)據(jù)庫性能:我們需要考慮到數(shù)據(jù)庫的性能問題,包括表的大小、索引的使用、查詢語句的優(yōu)化等。
- 數(shù)據(jù)庫安全:我們需要考慮到數(shù)據(jù)庫的安全問題,包括表的權(quán)限、用戶角色的設(shè)置等。
設(shè)計原則
在設(shè)計數(shù)據(jù)庫表結(jié)構(gòu)時,可以參考以下幾個優(yōu)雅的設(shè)計原則:
- 簡單明了:表結(jié)構(gòu)應(yīng)該簡單明了,避免過度復(fù)雜化。
- 一致性:表結(jié)構(gòu)應(yīng)該保持一致性,例如命名規(guī)范、數(shù)據(jù)類型等。
- 規(guī)范化:盡可能將表規(guī)范化,避免數(shù)據(jù)冗余和不一致性。
- 性能:表結(jié)構(gòu)應(yīng)該考慮到性能問題,例如使用適當(dāng)?shù)乃饕⒈苊馊頀呙璧取?/li>
- 安全:表結(jié)構(gòu)應(yīng)該考慮到安全問題,例如合理設(shè)置權(quán)限、避免SQL注入等。
- 擴(kuò)展性:表結(jié)構(gòu)應(yīng)該具有一定的擴(kuò)展性,例如預(yù)留字段、可擴(kuò)展的關(guān)系等。
最后,需要提醒的是,優(yōu)雅的數(shù)據(jù)庫表結(jié)構(gòu)需要在實踐中不斷迭代和優(yōu)化,不斷滿足實際需求和新的挑戰(zhàn)。
下面舉個示例讓大家更好的理解如何設(shè)計表結(jié)構(gòu),如何引入內(nèi)存,有哪些優(yōu)化思路:
問題描述
如上圖所示,紅框中的視頻篩選標(biāo)簽,應(yīng)該怎么設(shè)計數(shù)據(jù)庫表結(jié)構(gòu)?
這是一個很好的應(yīng)用場景,大家可以先自己想一下。不要著急看我的方案。
需求分析
- 可以根據(jù)紅框的標(biāo)簽篩選視頻
- 其中綜合標(biāo)簽比較特殊,和類型、地區(qū)、年份、演員等不一樣
- 綜合是根據(jù)業(yè)務(wù)邏輯取值,并不需要入庫
- 類型、地區(qū)、年份、演員等需要入庫
- 設(shè)計表結(jié)構(gòu)時要考慮到:
- 方便獲取標(biāo)簽信息,方便把標(biāo)簽信息緩存處理
- 方便根據(jù)標(biāo)簽篩選視頻,方便我們寫后續(xù)的業(yè)務(wù)邏輯
設(shè)計思路
- 綜合標(biāo)簽可以寫到配置文件中(或者寫在前端),這些信息不需要靈活配置,所以不需要保存到數(shù)據(jù)庫中
- 類型、地區(qū)、年份、演員都設(shè)計單獨的表
- 視頻表中設(shè)計標(biāo)簽表的外鍵,方便視頻列表篩選取值
- 標(biāo)簽信息寫入緩存,提高接口響應(yīng)速度
- 類型、地區(qū)、年份、演員表也要支持對數(shù)據(jù)排序,方便后期管理維護(hù)
表結(jié)構(gòu)設(shè)計
視頻表
字段 | 注釋 |
id | 視頻主鍵id |
type_id | 類型表外鍵id |
area_id | 地區(qū)表外鍵id |
year_id | 年份外鍵id |
actor_id | 演員外鍵id |
其他和視頻直接相關(guān)的字段(比如名稱)我就省略不寫了
類型表
字段 | 注釋 |
id | 類型主鍵id |
name | 類型名稱 |
sort | 排序字段 |
地區(qū)表
字段 | 注釋 |
id | 類型主鍵id |
name | 類型名稱 |
sort | 排序字段 |
年份表
字段 | 注釋 |
id | 類型主鍵id |
name | 類型名稱 |
要么是年份正序排列,要么是年份倒序排列,所以不需要sort字段
演員表
字段 | 注釋 |
id | 類型主鍵id |
name | 類型名稱 |
sort | 排序字段 |
表結(jié)構(gòu)設(shè)計完了,別忘了緩存
緩存策略
首先這些不會頻繁更新的篩選條件建議使用緩存:
- 比較常用的就是redis緩存
- 再進(jìn)階一點,如果你使用docker,可以把這些配置信息寫入docker容器所在物理機(jī)的內(nèi)存中,而不用請求其他節(jié)點的redis,進(jìn)一步降低網(wǎng)絡(luò)傳輸帶來的耗時損耗
- 篩選條件這類配置信息,客戶端和服務(wù)端可以約定一個更新緩存的機(jī)制,客戶端直接緩存配置信息,進(jìn)一步提高性能
列表數(shù)據(jù)自動緩存
目前很多框架都是支持自動緩存處理的,比如goframe和go-zero,官方文檔都做了詳細(xì)的介紹,不作為本文的重點。
goframe
可以使用ORM鏈?zhǔn)讲僮?查詢緩存[1]
官方示例:
go-zero
DB緩存機(jī)制[2]
go-zero緩存設(shè)計之持久層緩存[3]
官方文檔都做了詳細(xì)的介紹,不作為本文的重點。
總結(jié)
這篇文章介紹了設(shè)計數(shù)據(jù)庫表結(jié)構(gòu)應(yīng)該考慮的4個方面,還有優(yōu)雅設(shè)計的6個原則,舉了一個例子分享了我的設(shè)計思路,為了提高性能我們也要從多方面考慮緩存問題。
本文拋磚引玉,歡迎大家留言交流。
相關(guān)資料
[1]ORM鏈?zhǔn)讲僮?查詢緩存: https://goframe.org/pages/viewpage.action?pageId=1114346
[2]DB緩存機(jī)制: https://go-zero.dev/cn/docs/blog/cache/cache
[3]go-zero緩存設(shè)計之持久層緩存: https://go-zero.dev/cn/docs/blog/cache/redis-cache
本文轉(zhuǎn)載自微信公眾號「 程序員升級打怪之旅」,作者「王中陽Go」,可以通過以下二維碼關(guān)注。
轉(zhuǎn)載本文請聯(lián)系「 程序員升級打怪之旅」公眾號。