資料庫雜談之 如何優雅的進行表結構設計

2021-09-19 08:51:08 字數 2867 閱讀 5679

資料庫表結構設計作為後端軟體開發不可或缺的一環,是每個後端工程師都會經歷的過程。筆者也多次經歷過這樣的過程,也嘗試過多種不同的設計方案,也從一些優秀的框架中學到不少,但並沒有發現相關的文章對其進行總結。所以本文嘗試把筆者看到的、學到的總結下來,希望對閱讀本文的讀者有所啟發。

表結構設計主要有兩個目的,一是讓表結構更加的更具有表現力,做到資料庫表的自描述,減少注釋甚至不使用注釋;二是滿足系統效率和擴充套件性的需要,讓系統效能更好,後期維護更簡單。

本文主要**的是如何優雅的設計表結構,讓人能夠直觀的從命名中窺探設計意圖,傳達設計者的設計目的,讓團隊成員達成共識,減少溝通成本。本文不討論表結構設計對效能的影響,也不討論資料庫設計中的正規化與反正規化設計。本文將從資料庫表的命名和字段的命名兩個方面展開。

使用名詞作為表名

仔細想想便可發現,資料庫表中存在的所有資料都是現實世界各種操作的結果,它們有的是中間過程結果,有的是最終資料結果。不論怎樣,它們是乙份乙份沒有任何動作的,靜態的記錄。而表本身就是儲存這些記錄的容器,從這樣的層面理解,表名應該採用名詞的形式是完全符合邏輯的。

比如我們要設計乙個儲存使用者邀請的表,invitation 就比 invite 更加的優雅。

相關表採用統一字首

我們知道,大型系統的設計往往按模組或者子系統進行劃分,乙個乙個模組的處理問題,保證模組間的低耦合,模組內的高內聚。資料庫表設計也一樣,我們可以對相關聯的表採用相同的字首,使開發人員一眼看上去就知道哪幾個表是相關的。

user

user_profile

user_wechat

本節先介紹幾個比較通用的原則,使得欄位的含義更容易理解,描述性更強,之後進行簡單的總結分類,以便讓我們明白這些原則背後的邏輯。

使用動詞被動形式+描述性字尾

通過前面我們知道,資料庫表中的所有記錄都是靜態的結果性資料,它是由一定的使用者操作產生的。那麼它是如何產生的?經過什麼樣的操作產生的呢?

在解答之前先看乙個例子,下面是乙個簡單的 article 表結構:

id: integer

title: varchar

content: text

user_id: integer

create_time: timestamp

這樣的設計本身是沒有問題的,目前用的也很多。這個設計主要的問題是沒有體現出 user_id 與這篇文章的關係,需要經過一定的猜測和思考才能得出。create_time 雖然還比較直觀,但沒有體現出這篇文章實在過去的某個時間建立的。

然後我們在來看修改後的設計:

id: integer

title: varchar

content: text

created_by: integer

created_at: timestamp

通過把 user_id 替換為 created_by、create_time 替換為 created_at,使得我們更容易理解對應的文章是被指定的人在指定的時間建立出來的,而不需要我們的多方猜測或者查閱文件,使得整個表結構的描述性更強。

時間區分當前時間和未來時間

英語中表時間的時候, at 一般跟乙個時間點,而 in 有表示在未來的某個時間之內的意思。結合起來,筆者傾向於用 at 表示過去或者現在的時間,而用 in 表示未來的時間。比如日曆中的 event 有開始時間和結束時間的概念,我覺得如下的命名是比較合理的:

starts_at 事件的開始時間,相對 ends_in 它屬於當前時間,採用 _at 字尾

ends_in 事件的結束時間,相對 ends_in 它屬於未來時間,從用 _in 字尾

其他我們比較常用的比如 created_at、updated_at、expires_in 都屬於這種型別。

使用第三人稱單數

當我們採用動詞+介詞的時候我更傾向與使用第三人稱單數,因為字段描述的這個實體是單數的,通過使用第三人稱單數,我們可以自然語言的方式表達出需要的意思。比如以 event 為例,翻譯成英語是這樣的:

the event starts at 2016-05-05 12:00:00

完全符合英語的語法,也表達了我們想要表達的意思。

區分單數與複數

單數與複數主要是對字段內容的描述,比如通知(notification)有接收人這個字段,如果我們需要通知能夠傳送給多個人,那麼 receivers 這樣的欄位名稱明顯好於 receiver,因為 receivers 體現了通知可以傳送給多個人這乙個事實。

前面從四個原則出發介紹了如何讓字段更具有描述性,簡單總結下來我覺得從語義上來說,字段可以分為兩種型別:描述性字段動作性字段

描述性欄位是對對應資料庫記錄(或者說實體)的補充說明,比如以人作為實體,那麼人的身高、體重和血壓就屬於這類描述性字段。

描述性字段如果是動詞+介詞的形式,動詞需要採用第三人稱單數的形式,比如 starts_at。然後根據欄位的內容,如果內容有多個元素或實體,我們需要使用複數,否則使用單數形式。

動作性字段不僅能對所屬實體進行補充說明,還能對這個實體的所涉及操作有所描述。比如我們有 article 這個實體, article 的 created_by 和 created_at 就屬於動作性字段,因為它不僅表達了 article 的建立者和建立時間這層資訊,它還表達了這個 article 是指定的人被建立的,而不是憑空生成的。

2023年5月5日

北京

如何優雅的使用SQL資料庫表之間的連線?

一 首先,我們要理解資料庫的表連線方式有幾種。二 下面乙個乙個介紹他們的使用 先建立兩個表,乙個是學生表,另外乙個是成績表 學生表 student stdno stdname stdage std stdclass 001小白17女 1002 小李18女2 003小蔣18男 1004 小陳15女2 ...

如何對MySQL資料庫表進行鎖定

如果你同時執行表的檢查 修復程式時,你或許不想讓mysql伺服器和實用程式同時訪問乙個表。如果兩個程式都向表中寫資料顯然會造成很大的麻煩,甚至會有意外情況發生。如果表正由乙個程式寫入,同時進行讀取的另乙個程式也會產生混亂的結果。本文主要講述如何對mysql資料庫表進行鎖定。鎖定表的方法 防止客戶機的...

資料庫雜談之 MySQL延時複製庫

我相信很多人都遭遇過mysql主從複製延遲的問題,處理方案基本上就是你能搜尋到的那些,那麼我今天卻要說說如何讓mysql延遲複製。對於剛組建的團隊來說,這可能會救了你的專案。簡單的說延遲複製就是設定乙個固定的延遲時間,比如1個小時,讓從庫落後主庫乙個小時。存在即合理,延遲複製可以用來解決以下三類問題...