良好的邏輯設計與物理設計是高性能的基石,當我們在設計數據表結構的時候,應該跟根據業務邏輯來分析具體情況,然後設計出比較合理,高效的數據表結構
在數據表結構設計中,不得不提的就是範式
與數據類型
了
Mysql三範式
- 字段不可分;即字段具有原子性 字段不可再分,否則就不是關係數據庫;
- 有主鍵,非主鍵字段依賴主鍵; 唯一性 一個表只說明一個事物
- 非主鍵字段不能相互依賴;每列都與主鍵有直接關係,不存在傳遞依賴
範式的優點與缺點
-
優點
- 範式化設計更新通常比反範式化更新要快
- 當數據高度範式化時,就只有少量或者沒有重複數據,這樣修改的時候就只需要修改少量的數據
- 範式化的表通常比較小,可以更好的放在內存裏面,操作就會更容易
- 因爲範式化設計之後,冗餘數據較少,所以在執行某些查詢的時候可能就不會用到
group by
,distinct
這樣也提高了查詢效率
- 缺點
因爲嚴格遵循範式化設計的話。在某些業務場景下可能會查詢多個表。這樣的同樣會使得查詢效率變的很低。而且在某些時候因爲多表查詢的原因,可能某些索引不會被命中。
這裏我們看到範式化的設計有優點也有缺點,所以在實際的項目中,我們通常是混範式化設計。
某些表完全遵循範式化;某些表遵循部分範式化設計。在設計某些表的時候 會用到反範式化的思想,將某些數據存到同一張表中。這樣可以減少很多關聯查詢,也可以更好的去設計索引關係。
比如users
表 與user_messages
表中,都會保存一個user_account_type
字段。這樣的話,在單獨查詢user_account_type=1
的消息總數時就不需要再去關聯users
表了。
數據類型
Mysql支持的數據類型有很多種,所以選擇正確的數據類型對提高性能有着至關重要的作用。但是不管哪種數據類型我們都應該參考下面幾個原則
-
更小的通常更好
;更小的數據類型通常更快,因爲他們佔用更少的磁盤、內存、CPU緩存。 -
簡單就好
;操作簡單的數據類型通常需要更少的CPU週期。例如:整型比字符串操作代價更低 -
儘量避免NULL
;如果查詢中包含可爲Null
的列,對於Mysql
來說更難優化,因爲可以爲null
的列使得索引,索引統計和值都變的更加複雜
整數類型
Mysql
的整數類型有 TINYINT
,SMALLINT
,MEDIUMINT
,INT
,BIGINT
。他們使用到的儲存空間分別是,8
,16
,24
,32
,64
位。值的範圍是-2(N-1)到2(N-1)-1
整形可以選擇UNSIGNED
屬性,表示是否有符號,不允許爲負值。
如 TINYINT UNSIGNED 值的範圍 0~255, 而 TINYINT 值的範圍是-128-127。需要注意點是有符號跟無符號使用相同的儲存空間,擁有相同的性能,所以可以根據實際情況來選擇類型。
字符串類型
VARCHAR
,CHAR
是兩種最主要的字符串類型,
-
VARCHAR
類型用於儲存可變字符串,是常見的字符串類型。它比定長類型更節省空間。 -
CHAR
定長字符串類型,分配固定長度的空間。在保存某些定長字符串時比VARCHAR
更有優勢、比如md5
定長字符串,因爲定長類型字符串不容易產生碎片。
對於VARCHAR(5)
和VARCHAR(100)
儲存hello
的空間開銷是一樣的,那麼是不是我們就可以定義長度爲100
呢?當然不是了,更長的列會消耗更多的內存,因爲Mysql通常會分配固定大小的內存塊來保存內部值。所以最好的策略就是分配合理的長度,這樣就分配到真正需要的 空間。
日期,時間類型
-
DATETIME
類型,能夠保存1001-9999年,精度爲秒,與時區無關。 -
TIMESTAMP
類型,保存了從1970-01-01午夜到現在的秒數,只使用了4個字節,只能表示1970-2038年。TIMESTAMP
依賴於時區。TIMESTAMP
在默認情況下,如果沒有指定列的值,會把列的值設置爲當前時間,在更新的時候也可以更新列的值爲當前時間。
通常情況下應該儘量使用TIMESTAMP
,因爲它比DATETIME
空間效率更高,有時候我們會將Unix時間戳保存爲整數值以表示當前時間,實際上並不會帶來任何收益。
上面列舉了幾個常用的mysql
類型,在實際使用中可以根據業務選擇最優的方案。一般情況下遵循更小的通常更好
,簡單就好
,儘量避免NULL
是沒有問題的。
關於mysql的數據類型選擇,就寫到這裏。後面也會寫一些關於索引優化方面的文章,如果問題歡迎大家指出。