面試官問我,爲何老司機建議MySQL列屬性儘可能用 NOT NULL ?

本文閱讀時間大約6分鐘。html

其實寫這篇文章,也是來自一個知識星球讀者的提問,他在二面的過程當中被問到了,因爲他簡歷中寫道有 MySQL 調優經驗,但這個問題沒有回答好,二面被刷了。
java


其實咱們剛學習 C 語言的時候,就接觸過 NULL,好比下面這句代碼。mysql


int *p = NULL;面試


它實際上表示將指針指向一塊不被使用的內存地址,通常會在宏中定義好。redis


那麼咱們經常使用的 Java 語言,一樣也用到 null,表示一個空引用,若是你不當心引用了,那麼就會拋出 NullPointerException,就像昨天 Reddit 上面很火的一張圖。sql


640?wx_fmt=jpeg


關於空指針異常,我以前寫過一篇文章來介紹怎麼防護《java.lang.NullPointerException》。可是這篇文章沒有寫全,今天在這裏補充一下。
後端


其實很早以前 guava 就提供了 Optional 容器類來處理 null,其目的即是避免猝不及防的空指針。後來 java8 直接引入了 Optional,功能同樣,用法上稍稍有點變化。其實還有不少開源框架,好比 Spring,common lang3等,也提供了處理空的工具類,如。app


StringUtils.isBlank();   框架


CollectionUtils.isEmpty();函數


那麼在 MySQL 中,NULL 表示不知道的數據。


咱們在設計表的時候,常常會有老司機這麼告訴咱們。


字段儘量用NOT NULL,而不是NULL,除非特殊狀況。


這句話到底有沒有錯?


能夠負責任的告訴你這句話沒有錯,也不是以訛傳訛。


這句話首次出如今 MySQL 官網。


640?wx_fmt=png

若是你讀過《高性能 MySQL》這本書,你應該會看到這麼一段,在 4.1 節提到。

640?wx_fmt=png


由此看來,把 NULL 改爲 NOT NULL 對索引的性能並無明顯的提高。避免使用 NULL 的目的,是便於代碼的可讀性和可維護性。同時也便於避免下文即將出現的一些稀奇古怪的錯誤。


好了,下面我們經過實驗來看看,使用 NULL 會出現那些稀奇古怪的錯誤呢?


跟我同樣在本地建兩個表 t1,t2;其中一個表 name 字段容許爲空,另外一個表 name 字段不容許爲空,分別對 name 字段創建索引,SQL 語句以下。


640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

一、NOT IN、!= 等負向條件查詢在有 NULL 值的狀況下返回非空行的結果集。


好比上例中的 t2,我執行以下 SQL 語句。


SELECT * from t2 where name != '張三'


你本打算返回 id 爲 2 的那行數據,然而什麼都沒有。


640?wx_fmt=png


又好比這條 SQL 語句。


select * from t2 where name not in (select name from t2 where id!=1)


也返回了空結果集。


二、使用 concat 函數拼接時,首先要對各個字段進行非 NULL 判斷,不然只要任何一個字段爲空都會形成拼接的結果爲 NULL。


好比下面這條 SQL 語句。


SELECT CONCAT("1",NULL)


640?wx_fmt=png


三、當用count函數進行統計時,NULL 列不會計入統計。


SELECT count(name) from t2


640?wx_fmt=png


四、查詢空行數據,用 is NULL。


SELECT * FROM t2 where name is NULL


640?wx_fmt=png


五、NULL 列須要更多的存儲空間,通常須要一個額外的字節做爲判斷是否爲 NULL 的標誌位。


若是你仔細觀察 t1 和 t2 表的 key_len,會發現 t2 比 t1 多了一個字節。


explain SELECT * from t2 where name = '張三'


640?wx_fmt=png


explain SELECT * from t1 where name = '張三'


640?wx_fmt=png


key_len 的長度通常跟這三個因素有關,分別是數據類型字符編碼是否爲 NULL


所以,t2 比 t1 多出的這一個字節,用於做爲判斷是否爲 NULL 的標誌位了。


馬蛋,原來一切都在書中。若是面試的哪位同窗多讀幾篇《高性能 MySQL》這本書,那個崗位就是他的了,但沒有那麼多若是。。。


在此,建議你們多看官方文檔,多讀點好書,多關注一些良心的原創技術自媒體,不要看那些無憑無據的文章,反而會以訛傳訛,貽害無窮。


若是這篇文章對你有幫助,麻煩分享到你的朋友圈,來幫助更多的朋友。


參考

https://dev.mysql.com/doc/refman/5.7/en/dynamic-format.html

https://dev.mysql.com/doc/refman/5.5/en/problems-with-null.html

https://dev.mysql.com/doc/refman/5.5/en/multiple-column-indexes.html

https://dev.mysql.com/doc/internals/en/myisam-introduction.html

https://dev.mysql.com/doc/internals/en/innodb-field-contents.html


640?wx_fmt=png下方查看 歷史文章 640?wx_fmt=png

面試官:講講redis的過時策略如何實現?

【譯】深刻理解G1的GC日誌(一)

使用Optional擺脫NPE的折磨

025:爲何須要將Logger對象聲明爲private static final類型的

本號專一於後端技術、JVM問題排查和優化、Java面試題、我的成長和自我管理等主題,爲讀者提供一線開發者的工做和成長經驗,期待你能在這裏有所收穫。

640?wx_fmt=png

讓我知道你「在看」 640?wx_fmt=gif
相關文章
相關標籤/搜索