国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

數據庫字段要使用NOT NULL究竟是為何?

數據分析與開發 ? 來源:博客園 ? 作者:艾小仙 ? 2021-04-19 15:24 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

最近剛入職新公司,發現數據庫設計有點小問題,數據庫字段很多沒有NOT NULL,對于強迫癥晚期患者來說,簡直難以忍受,因此有了這篇文章。

基于目前大部分的開發現狀來說,我們都會把字段全部設置成NOT NULL并且給默認值的形式。

通常,對于默認值一般這樣設置:

整形,我們一般使用0作為默認值。

字符串,默認空字符串

時間,可以默認1970-01-01 0801,或者默認0000-00-00 0000,但是連接參數要添加zeroDateTimeBehavior=convertToNull,建議的話還是不要用這種默認的時間格式比較好

但是,考慮下原因,為什么要設置成NOT NULL?

來自高性能Mysql中有這樣一段話:

盡量避免NULL

很多表都包含可為NULL(空值)的列,即使應用程序并不需要保存NULL也是如此,這是因為可為NULL是列的默認屬性。通常情況下最好指定列為NOT NULL,除非真的需要存儲NULL值。

如果查詢中包含可為NULL的列,對MySql來說更難優化,因為可為NULL的列使得索引、索引統計和值比較都更復雜。可為NULL的列會使用更多的存儲空間,在MySql里也需要特殊處理。當可為NULL的列被索引時,每個索引記錄需要一個額外的字節,在MyISAM里甚至還可能導致固定大小的索引(例如只有一個整數列的索引)變成可變大小的索引。

通常把可為NULL的列改為NOT NULL帶來的性能提升比較小,所以(調優時)沒有必要首先在現有schema中查找并修改掉這種情況,除非確定這會導致問題。但是,如果計劃在列上建索引,就應該盡量避免設計成可為NULL的列。

當然也有例外,例如值得一提的是,InnoDB使用單獨的位(bit)存儲NULL值,所以對于稀疏數據有很好的空間效率。但這一點不適用于MyISAM。

書中的描述說了幾個主要問題,我這里暫且拋開MyISAM的問題不談,這里我針對InnoDB作為考量條件。

如果不設置NOT NULL的話,NULL是列的默認值,如果不是本身需要的話,盡量就不要使用NULL

使用NULL帶來更多的問題,比如索引、索引統計、值計算更加復雜,如果使用索引,就要避免列設置成NULL

如果是索引列,會帶來的存儲空間的問題,需要額外的特殊處理,還會導致更多的存儲空間占用

對于稀疏數據有更好的空間效率,稀疏數據指的是很多值為NULL,只有少數行的列有非NULL值的情況

默認值

對于MySql而言,如果不主動設置為NOT NULL的話,那么插入數據的時候默認值就是NULL。

NULL和NOT NULL使用的空值代表的含義是不一樣,NULL可以認為這一列的值是未知的,空值則可以認為我們知道這個值,只不過他是空的而已。

舉個例子,一張表中的某一條name字段是NULL,我們可以認為不知道名字是什么,反之如果是空字符串則可以認為我們知道沒有名字,他就是一個空值。

而對于大多數程序的情況而言,沒有什么特殊需要非要字段要NULL的吧,NULL值反而會對程序造成比如空指針的問題。

對于現狀大部分使用MyBatis的情況來說,我建議使用默認生成的insertSelective方法或者純手動寫插入方法,可以避免新增NOT NULL字段導致的默認值不生效或者插入報錯的問題。

值計算

聚合函數不準確

對于NULL值的列,使用聚合函數的時候會忽略NULL值。

現在我們有一張表,name字段默認是NULL,此時對name進行count得出的結果是1,這個是錯誤的。

count(*)是對表中的行數進行統計,count(name)則是對表中非NULL的列進行統計。

5e7ffcca-9f5a-11eb-8b86-12bb97331649.jpg

=失效

對于NULL值的列,是不能使用=表達式進行判斷的,下面對name的查詢是不成立的,必須使用is NULL。

5e908a04-9f5a-11eb-8b86-12bb97331649.jpg

與其他值運算

NULL和其他任何值進行運算都是NULL,包括表達式的值也是NULL。

user表第二條記錄age是NULL,所以+1之后還是NULL,name是NULL,進行concat運算之后結果還是NULL。

5e98c872-9f5a-11eb-8b86-12bb97331649.jpg

可以再看下下面的例子,任何和NULL進行運算的話得出的結果都會是NULL,想象下你設計的某個字段如果是NULL還不小心進行各種運算,最后得出的結果。。。

5ea43040-9f5a-11eb-8b86-12bb97331649.jpg

distinct、group by、order by

對于distinct和group by來說,所有的NULL值都會被視為相等,對于order by來說升序NULL會排在最前

5eca059a-9f5a-11eb-8b86-12bb97331649.jpg

其他問題

表中只有一條有名字的記錄,此時查詢名字!=a預期的結果應該是想查出來剩余的兩條記錄,會發現與預期結果不匹配。

5ed4b576-9f5a-11eb-8b86-12bb97331649.jpg

索引問題

為了驗證NULL字段對索引的影響,分別對name和age添加索引。

5eea93f0-9f5a-11eb-8b86-12bb97331649.jpg

關于網上很多說如果NULL那么不能使用索引的說法,這個描述其實并不準確,根據引用官方文檔[3]里描述,使用is NULL和范圍查詢都是可以和正常一樣使用索引的,實際驗證的結果好像也是這樣,看以下例子。

5ef74ffa-9f5a-11eb-8b86-12bb97331649.jpg

然后接著我們往數據庫中繼續插入一些數據進行測試,當NULL列值變多之后發現索引失效了。

5f027aec-9f5a-11eb-8b86-12bb97331649.jpg

我們知道,一個查詢SQL執行大概是這樣的流程:

5f0caefe-9f5a-11eb-8b86-12bb97331649.jpg

首先連接器負責連接到指定的數據庫上,接著看看查詢緩存中是否有這條語句,如果有就直接返回結果。

如果緩存沒有命中的話,就需要分析器來對SQL語句進行語法和詞法分析,判斷SQL語句是否合法。

現在來到優化器,就會選擇使用什么索引比較合理,SQL語句具體怎么執行的方案就確定下來了。

最后執行器負責執行語句、有無權限進行查詢,返回執行結果。

從上面的簡單測試結果其實可以看到,索引列存在NULL就會存在書中所說的導致優化器在做索引選擇的時候更復雜,更加難以優化。

存儲空間

數據庫中的一行記錄在最終磁盤文件中也是以行的方式來存儲的,對于InnoDB來說,有4種行存儲格式:REDUNDANT、COMPACT、DYNAMIC和COMPRESSED。

InnoDB的默認行存儲格式是COMPACT,存儲格式如下所示,虛線部分代表可能不一定會存在。

5f14e5e2-9f5a-11eb-8b86-12bb97331649.jpg

變長字段長度列表:有多個字段則以逆序存儲,我們只有一個字段所有不考慮那么多,存儲格式是16進制,如果沒有變長字段就不需要這一部分了。

NULL值列表:用來存儲我們記錄中值為NULL的情況,如果存在多個NULL值那么也是逆序存儲,并且必須是8bit的整數倍,如果不夠8bit,則高位補0。1代表是NULL,0代表不是NULL。如果都是NOT NULL那么這個就存在了。

ROW_ID:一行記錄的唯一標志,沒有指定主鍵的時候自動生成的ROW_ID作為主鍵。

TRX_ID:事務ID。

ROLL_PRT:回滾指針。

最后就是每列的值。

為了說明清楚這個存儲格式的問題,我弄張表來測試,這張表只有c1字段是NOT NULL,其他都是可以為NULL的。

5f25503a-9f5a-11eb-8b86-12bb97331649.jpg

可變字段長度列表:c1和c3字段值長度分別為1和2,所以長度轉換為16進制是0x01 0x02,逆序之后就是0x02 0x01。

NULL值列表:因為存在允許為NULL的列,所以c2,c3,c4分別為010,逆序之后還是一樣,同時高位補0滿8位,結果是00000010。

其他字段我們暫時不管他,最后第一條記錄的結果就是,當然這里我們就不考慮編碼之后的結果了。

5f464196-9f5a-11eb-8b86-12bb97331649.jpg

這樣就是一個完整的數據行數據的格式,反之,如果我們把所有字段都設置為NOT NULL,并且插入一條數據a,bb,ccc,dddd的話,存儲格式應該這樣:

5f55fdf2-9f5a-11eb-8b86-12bb97331649.jpg

雖然我們發現NULL本身并不會占用存儲空間,但是如果存在NULL的話就會多占用一個字節的標志位的空間。

文章參考文檔:

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

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • SQL
    SQL
    +關注

    關注

    1

    文章

    789

    瀏覽量

    46700
  • 數據庫
    +關注

    關注

    7

    文章

    4020

    瀏覽量

    68344
  • 函數
    +關注

    關注

    3

    文章

    4417

    瀏覽量

    67504
  • null
    +關注

    關注

    0

    文章

    19

    瀏覽量

    4306

原文標題:為什么數據庫字段要使用NOT NULL?

文章出處:【微信號:DBDevs,微信公眾號:數據分析與開發】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    艾體寶干貨 | 多模型數據庫解決的到底是什么問題?

    了其設計的核心初衷。要精準理解多模型數據庫,需先跳出“功能誤區”,回歸問題本質:企業系統的數據庫復雜度,究竟源于何處? 系統變復雜,往往不只是因為數據量,還有
    的頭像 發表于 02-03 16:08 ?315次閱讀

    國產數據庫的AI戰事

    國產數據庫硝煙再起,Vastbase V100構筑企業智能基座
    的頭像 發表于 10-24 20:45 ?4024次閱讀
    國產<b class='flag-5'>數據庫</b>的AI戰事

    華納云為游戲數據庫選擇高性能NVMe SSD存儲

    的關鍵因素,尤其是在香港服務器租用環境中。 為何游戲數據庫需要高性能存儲 游戲數據庫因其動態化和實時性需求,與傳統數據庫存在顯著差異。這些需求包括: 高并發,可處理數千名玩家的同時交互
    的頭像 發表于 09-30 16:03 ?1071次閱讀

    數據庫性能優化指南

    作為一名在大廠摸爬滾打多年的運維老兵,我見過太多因為數據庫性能問題導致的生產事故。今天分享一套完整的數據庫優化方法論,從SQL層面到硬件配置,幫你徹底解決性能瓶頸!
    的頭像 發表于 08-18 11:21 ?745次閱讀

    數據庫數據恢復—服務器異常斷電導致Oracle數據庫故障的數據恢復案例

    Oracle數據庫故障: 某公司一臺服務器上部署Oracle數據庫。服務器意外斷電導致數據庫報錯,報錯內容為“system01.dbf需要更多的恢復來保持一致性”。該Oracle數據庫
    的頭像 發表于 07-24 11:12 ?640次閱讀
    <b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復—服務器異常斷電導致Oracle<b class='flag-5'>數據庫</b>故障的<b class='flag-5'>數據</b>恢復案例

    三款主流國產數據庫的技術特點

    隨著數字經濟的快速發展和數據安全要求的提升,國產數據庫正迎來前所未有的發展機遇。在信創浪潮推動下,達夢數據庫、TiDB、華為高斯數據庫等國產數據庫
    的頭像 發表于 07-14 11:08 ?1148次閱讀

    數據庫數據恢復—MongoDB數據庫文件丟失的數據恢復案例

    MongoDB數據庫數據恢復環境: 一臺操作系統為Windows Server的虛擬機上部署MongoDB數據庫。 MongoDB數據庫故障: 工作人員在MongoDB服務仍
    的頭像 發表于 07-01 11:13 ?640次閱讀
    <b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復—MongoDB<b class='flag-5'>數據庫</b>文件丟失的<b class='flag-5'>數據</b>恢復案例

    數據庫數據恢復—SQL Server數據庫被加密如何恢復數據

    SQL Server數據庫故障: SQL Server數據庫被加密,無法使用。 數據庫MDF、LDF、log日志文件名字被篡改。
    的頭像 發表于 06-25 13:54 ?673次閱讀
    <b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復—SQL Server<b class='flag-5'>數據庫</b>被加密如何恢復<b class='flag-5'>數據</b>?

    大促數據庫壓力激增,如何一眼定位 SQL 執行來源?

    你是否曾經遇到過這樣的情況:在大促活動期間,用戶訪問量驟增,數據庫的壓力陡然加大,導致響應變慢甚至服務中斷?更讓人頭疼的是,當你試圖快速定位問題所在時,卻發現難以確定究竟是哪個業務邏輯中的 SQL
    的頭像 發表于 06-10 11:32 ?565次閱讀
    大促<b class='flag-5'>數據庫</b>壓力激增,如何一眼定位 SQL 執行來源?

    oracle數據恢復—oracle數據庫誤執行錯誤truncate命令如何恢復數據

    oracle數據庫誤執行truncate命令導致數據丟失是一種常見情況。通常情況下,oracle數據庫誤操作刪除數據只需要通過備份恢復數據
    的頭像 發表于 06-05 16:01 ?1074次閱讀
    oracle<b class='flag-5'>數據</b>恢復—oracle<b class='flag-5'>數據庫</b>誤執行錯誤truncate命令如何恢復<b class='flag-5'>數據</b>?

    SQLSERVER數據庫是什么

    SQL Server 是由微軟公司開發的一款 關系型數據庫管理系統(RDBMS) ,用于存儲、管理和檢索結構化數據。它是企業級應用中廣泛使用的數據庫解決方案之一,尤其適用于Windows平臺,但也
    的頭像 發表于 05-26 09:19 ?1172次閱讀

    MySQL數據庫是什么

    開發、企業應用和大數據場景。以下是其核心特性和應用場景的詳細說明: 核心特性 關系型數據庫模型 數據以 表(Table) 形式組織,表由行(記錄)和列(字段)構成。 通過 主鍵、外鍵
    的頭像 發表于 05-23 09:18 ?1208次閱讀

    FOC電機控制究竟該如何學?

    學習FOC電機控制究竟是學哪些內容? 電機知識 軟件知識 純分享貼,有需要可以直接下載附件獲取完整資料! (如果內容有幫助可以關注、點贊、評論支持一下哦~)
    發表于 05-09 14:09

    SEGGER emFile支持大型數據庫

    SEGGER宣布emFile對大型數據庫的支持,集成了SQLite,方便與SEGGER的BigFAT和微軟的exFAT一起使用。
    的頭像 發表于 04-23 15:51 ?777次閱讀

    數據庫數據恢復——MongoDB數據庫文件拷貝后服務無法啟動的數據恢復

    MongoDB數據庫數據恢復環境: 一臺Windows Server操作系統虛擬機上部署MongoDB數據庫。 MongoDB數據庫故障: 管理員在未關閉MongoDB服務的
    的頭像 發表于 04-09 11:34 ?867次閱讀
    <b class='flag-5'>數據庫</b><b class='flag-5'>數據</b>恢復——MongoDB<b class='flag-5'>數據庫</b>文件拷貝后服務無法啟動的<b class='flag-5'>數據</b>恢復