為什么數(shù)據(jù)庫字段要使用NOT NULL?
往期熱門文章:
1、《往期精選優(yōu)秀博文都在這里了!》 2、CTO 說了,用錯 @Autowired 和 @Resource 的人可以領盒飯了 3、程序員離職事件始末 4、如何解決MySQL order by limit語句的分頁數(shù)據(jù)重復問題? 5、Java中八個潛在的內存泄露風險,你知道幾個?
最近剛入職新公司,發(fā)現(xiàn)數(shù)據(jù)庫設計有點小問題,數(shù)據(jù)庫字段很多沒有NOT NULL,對于強迫癥晚期患者來說,簡直難以忍受,因此有了這篇文章。
基于目前大部分的開發(fā)現(xiàn)狀來說,我們都會把字段全部設置成NOT NULL并且給默認值的形式。
通常,對于默認值一般這樣設置:
整形,我們一般使用0作為默認值。 字符串,默認空字符串 時間,可以默認 1970-01-01 08:00:01,或者默認0000-00-00 00:00:00,但是連接參數(shù)要添加zeroDateTimeBehavior=convertToNull,建議的話還是不要用這種默認的時間格式比較好
盡量避免NULL 很多表都包含可為NULL(空值)的列,即使應用程序并不需要保存NULL也是如此,這是因為可為NULL是列的默認屬性。通常情況下最好指定列為NOT NULL,除非真的需要存儲NULL值。 如果查詢中包含可為NULL的列,對MySql來說更難優(yōu)化,因為可為NULL的列使得索引、索引統(tǒng)計和值比較都更復雜。可為NULL的列會使用更多的存儲空間,在MySql里也需要特殊處理。當可為NULL的列被索引時,每個索引記錄需要一個額外的字節(jié),在MyISAM里甚至還可能導致固定大小的索引(例如只有一個整數(shù)列的索引)變成可變大小的索引。 通常把可為NULL的列改為NOT NULL帶來的性能提升比較小,所以(調優(yōu)時)沒有必要首先在現(xiàn)有schema中查找并修改掉這種情況,除非確定這會導致問題。但是,如果計劃在列上建索引,就應該盡量避免設計成可為NULL的列。 當然也有例外,例如值得一提的是,InnoDB使用單獨的位(bit)存儲NULL值,所以對于稀疏數(shù)據(jù)有很好的空間效率。但這一點不適用于MyISAM。
如果不設置NOT NULL的話,NULL是列的默認值,如果不是本身需要的話,盡量就不要使用NULL 使用NULL帶來更多的問題,比如索引、索引統(tǒng)計、值計算更加復雜,如果使用索引,就要避免列設置成NULL 如果是索引列,會帶來的存儲空間的問題,需要額外的特殊處理,還會導致更多的存儲空間占用 對于稀疏數(shù)據(jù)有更好的空間效率,稀疏數(shù)據(jù)指的是很多值為NULL,只有少數(shù)行的列有非NULL值的情況
默認值
name字段是NULL,我們可以認為不知道名字是什么,反之如果是空字符串則可以認為我們知道沒有名字,他就是一個空值。MyBatis的情況來說,我建議使用默認生成的insertSelective方法或者純手動寫插入方法,可以避免新增NOT NULL字段導致的默認值不生效或者插入報錯的問題。值計算
name字段默認是NULL,此時對name進行count得出的結果是1,這個是錯誤的。count(*)是對表中的行數(shù)進行統(tǒng)計,count(name)則是對表中非NULL的列進行統(tǒng)計。
=表達式進行判斷的,下面對name的查詢是不成立的,必須使用is NULL。
user表第二條記錄age是NULL,所以+1之后還是NULL,name是NULL,進行concat運算之后結果還是NULL。

distinct和group by來說,所有的NULL值都會被視為相等,對于order by來說升序NULL會排在最前
!=a預期的結果應該是想查出來剩余的兩條記錄,會發(fā)現(xiàn)與預期結果不匹配。
索引問題
name 和age添加索引。



存儲空間
REDUNDANT、 COMPACT、 DYNAMIC 和 COMPRESSED。COMPACT,存儲格式如下所示,虛線部分代表可能不一定會存在。
c1字段是NOT NULL,其他都是可以為NULL的。
c1和c3字段值長度分別為1和2,所以長度轉換為16進制是0x01 0x02,逆序之后就是0x02 0x01。c2,c3,c4分別為010,逆序之后還是一樣,同時高位補0滿8位,結果是00000010。
a,bb,ccc,dddd的話,存儲格式應該這樣:
文章參考文檔:
https://dev.mysql.com/doc/refman/8.0/en/problems-with-null.html https://dev.mysql.com/doc/refman/8.0/en/working-with-null.html https://dev.mysql.com/doc/refman/5.6/en/is-null-optimization.html https://dev.mysql.com/doc/refman/5.6/en/innodb-row-format.html https://www.cnblogs.com/zhoujinyi/articles/2726462.html
往期熱門文章:
1、《歷史文章分類導讀列表!精選優(yōu)秀博文都在這里了!》
2、一個牛逼的 多級緩存 實現(xiàn)方案! 3、阿里一面:如何保障消息100%投遞成功、消息冪等性? 4、GitHub 熱榜:被網(wǎng)友瘋狂惡搞的「螞蟻呀嘿」項目終于開源了! 5、記住!看小電影前一定要檢查一下域名是不是 HTTPS 的,不然.... 6、拿到年終獎后馬上辭職,厚道嗎? 7、Redis 內存滿了怎么辦? 8、在 IDE 中玩轉 GitHub 9、死磕18個Java8日期處理,工作必用! 10、把我坑慘的一個MySQL雙引號!
評論
圖片
表情
