本文閱讀時間大約6分鐘。html
其實寫這篇文章,也是來自一個知識星球讀者的提問,他在二面的過程當中被問到了,因爲他簡歷中寫道有 MySQL 調優經驗,但這個問題沒有回答好,二面被刷了。
java
其實咱們剛學習 C 語言的時候,就接觸過 NULL,好比下面這句代碼。mysql
int *p = NULL;面試
它實際上表示將指針指向一塊不被使用的內存地址,通常會在宏中定義好。redis
那麼咱們經常使用的 Java 語言,一樣也用到 null,表示一個空引用,若是你不當心引用了,那麼就會拋出 NullPointerException,就像昨天 Reddit 上面很火的一張圖。sql
關於空指針異常,我以前寫過一篇文章來介紹怎麼防護《java.lang.NullPointerException》。可是這篇文章沒有寫全,今天在這裏補充一下。
後端
其實很早以前 guava 就提供了 Optional 容器類來處理 null,其目的即是避免猝不及防的空指針。後來 java8 直接引入了 Optional,功能同樣,用法上稍稍有點變化。其實還有不少開源框架,好比 Spring,common lang3等,也提供了處理空的工具類,如。app
StringUtils.isBlank(); 框架
CollectionUtils.isEmpty();函數
那麼在 MySQL 中,NULL 表示不知道的數據。
咱們在設計表的時候,常常會有老司機這麼告訴咱們。
字段儘量用NOT NULL,而不是NULL,除非特殊狀況。
這句話到底有沒有錯?
能夠負責任的告訴你這句話沒有錯,也不是以訛傳訛。
這句話首次出如今 MySQL 官網。
若是你讀過《高性能 MySQL》這本書,你應該會看到這麼一段,在 4.1 節提到。
由此看來,把 NULL 改爲 NOT NULL 對索引的性能並無明顯的提高。避免使用 NULL 的目的,是便於代碼的可讀性和可維護性。同時也便於避免下文即將出現的一些稀奇古怪的錯誤。
好了,下面我們經過實驗來看看,使用 NULL 會出現那些稀奇古怪的錯誤呢?
跟我同樣在本地建兩個表 t1,t2;其中一個表 name 字段容許爲空,另外一個表 name 字段不容許爲空,分別對 name 字段創建索引,SQL 語句以下。
一、NOT IN、!= 等負向條件查詢在有 NULL 值的狀況下返回非空行的結果集。
好比上例中的 t2,我執行以下 SQL 語句。
SELECT * from t2 where name != '張三'
你本打算返回 id 爲 2 的那行數據,然而什麼都沒有。
又好比這條 SQL 語句。
select * from t2 where name not in (select name from t2 where id!=1)
也返回了空結果集。
二、使用 concat 函數拼接時,首先要對各個字段進行非 NULL 判斷,不然只要任何一個字段爲空都會形成拼接的結果爲 NULL。
好比下面這條 SQL 語句。
SELECT CONCAT("1",NULL)
三、當用count函數進行統計時,NULL 列不會計入統計。
SELECT count(name) from t2
四、查詢空行數據,用 is NULL。
SELECT * FROM t2 where name is NULL
五、NULL 列須要更多的存儲空間,通常須要一個額外的字節做爲判斷是否爲 NULL 的標誌位。
若是你仔細觀察 t1 和 t2 表的 key_len,會發現 t2 比 t1 多了一個字節。
explain SELECT * from t2 where name = '張三'
explain SELECT * from t1 where name = '張三'
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
025:爲何須要將Logger對象聲明爲private static final類型的
本號專一於後端技術、JVM問題排查和優化、Java面試題、我的成長和自我管理等主題,爲讀者提供一線開發者的工做和成長經驗,期待你能在這裏有所收穫。
讓我知道你「在看」