【Web總結】資料庫系統

JerryCheese發表於2018-07-25

我的原文:www.hijerry.cn/p/6196.html

前言

資料也是Web應用最重要的部分,而資料庫恰好也是Web應用最容易出瓶頸的地方。經過幾年的學習、實踐我逐漸總結出了一套自己的資料庫設計、實踐原則,有一些是參考企業的,同時自己的優化方法也在裡面。

選擇合適的資料庫

Mysql是目前的主流資料庫之一,幾乎可以承擔起所有Web站點的資料處理操作(通過叢集、主從等優化手段)。

大型應用會使用Oracel作為資料庫(比如銀行、證券、電信)。

另外值得一提的是NOSQL,由於它的靈活性高於關係型資料庫,所以常用於作為快取系統,如MemCache、Redis。

目前JS全棧流派會使用MongoDB作為後臺資料庫。即便如此,我還是推薦使用關係型資料庫作為主資料庫,而NOSQL作為輔助資料庫。

一些原則

以下的設計都是基於Mysql的。

正規化和冗餘

關係型資料庫的正規化有六種,這是理論上的。

在實際開發中,往往達到第三正規化即可,並新增一些冗餘欄位以方便查詢。

主外來鍵

建立邏輯上的主外來鍵,但不建立硬性的主外來鍵關係。

邏輯上的主外來鍵意味著主外來鍵關係的維護交於程式來完成,而不是資料庫系統。這樣可以避免主外來鍵衝突而引起的不必要bug。

儘量不使用組合主鍵。

欄位型別和大小

在為一個欄位指定型別時,儘量使用整數型別。因為查詢效率高,儲存空間小。

整數型別欄位,儘量使用 unsigned 。如果確實需要表示負數,那就用有符號的整數型別。

如果欄位長度已知,務必使用char而不是varcharvarchar容易產生資料碎片,影響效率。比如儲存MD5雜湊值。

儘量避免可空欄位,並給欄位設定預設值。NULL 是一個非常噁心的東西,可能會引起索引分裂,並且有時候會引起意料之外的BUG。

索引

不要隨意建立索引,應當根據慢查詢建立適當的索引。比如經常需要排序、分組的欄位,可以建立索引。

把組合主鍵、值唯一的欄位建立為唯一索引。

儘量使用資料量比較少的索引。比如在整數型別上建立,而不是在文字型別上。這也意味著,在對 text 等資料量比較大的欄位建立索引時,應取欄位的前面幾個字元建立索引即可,而不是建立全文索引。

儘量選擇取值範圍更大的欄位建立索引。比如我們不應該在 性別欄位上建立索引,因為它的取值太有限了。

儘量擴充套件索引,而不是建立一個新的。比如已有索引(user_id),現在要建立class_id的索引,可以考慮建立為(user_id, class_id)。

索引的建立是否恰當,最終取決於查詢速度是否提高了。所以建議根據慢查詢日誌來建立適當的索引。

編碼

儘量使用utf8mb4編碼,這是四位元組的UTF-8編碼,是符合標準意義的。而utf8編碼是用三位元組存的,所以不能儲存emoji表情。

查詢

儘量避免大SQL查詢。

儘量基於索引查詢。

比起構造一個複雜的SQL查詢做一次查詢,簡單、短小的基於索引的多次查詢效率會更高。

例項:使用者表

這張表取自我的畢業設計,先看錶結構:

mark

上面所有的整數型別都是 unsigned 型別的

  • id 主鍵欄位必有
  • type 標識使用者型別。unsigned tinyint(0~255)足矣。
  • login 登入名。必須是變長的,因為這是使用者設定的,最多不超過 32 字元。
  • telephone 手機號碼。也可以用 bigint 儲存。也可以用 char(11) 來存,也可以用 char(13) 來存(區號2位),這裡用了 varchar(24) 是考慮到不同國家長度也不一樣,乾脆用變長字元來存了。
  • email 郵箱地址。目前最長的郵箱是 32 字元,理論最長是 320 字元,這裡折中取了 128 字元。
  • password 密碼。這裡是是使用 Hash:make 方法生成的,最長只有 60 位,所以長度是 60,並且為了避免編碼問題,使用 binary 欄位來儲存。
  • gender 性別。也可以使用 enum 儲存,但強烈不推薦,更何況只是用來儲存整數形式的內容。所以直接用 tinyint 型別。
  • register_iplast_login_ip 。ipv4地址。32 位的ipv4地址正好可以用一個int型別儲存。php裡使用ip2long函式即可完成轉換。如果遇到 ipv6 地址,就需要用 binary(16) 來存了。
  • create_timeupdate_timedelete_time 是Laravel框架所使用的用於記錄資料時間的欄位,所以沒辦法設定為了 可以為空

看看索引:

UNIQUE KEY `type` (`type`,`login`)
複製程式碼

這主要用於區分不同型別的使用者。

相關文章