01.07 Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)


NULL 和 空值的區別

● 本質區別

空值不佔空間,用''表示

NULL 值佔空間,用NULL表示

空值代表杯子是真空的,NULL 代表杯子中裝滿了空氣,2 個杯子看起來一樣,但是有本質的區別

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

MySql 官方:

“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”

NULL 佔空間


NULL 和 空值的保存問題

以 varchar 類型

● 如果字段是 NOT NULL

可以保存空值,不能保存 NULL值

● 如果字段是 NULL

可以保存空值和 NULL 值

字段類型是 NOT NULL,為什麼可以插入空值?

NULL 表示未知,沒有類型可言,而 '' 是有類型的,表示一個空的字符串。所以有NOT NULL 約束的列是可以插入 '' 的。


NULL 和空值對聚合函數的影響

● COUNT(expr)

在進行 COUNT(expr) 統計某列的記錄數的時候,如果採用的是 NULL 值,系統會自動忽略,但是空值是會進行統計到其中的

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

>>> SELECT COUNT(NAME) FROM USER ;

>>> 3

● AVG(expr)

name 是 varchar 類型

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

>>>SELECT AVG(NAME) FROM USER ;

>>>2.25

我們可以看出:MySql 在計算 AVG(expr) 時 會自動將 NULL 值過濾掉不參與計算,但是不排除空值

● MIN(expr)

>>>SELECT MIN(NAME) FROM USER ;

>>>''

我們可以看出:MySql 在計算 MIN(expr) 時 會自動將 NULL 值過濾掉不參與計算,但是不排除空值



NULL 和空值對 order by 和 group by 的影響


Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

原表

>>> SELECT * FROM USER ORDER BY NAME;

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

>>> SELECT * FROM USER GROUP BY NAME;

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)


MySql 對空值或者 NULL 的判斷

圍觀下《阿里巴巴開發手冊》中 MySql 部分描述

●【強制】使用 ISNULL()來判斷是否為 NULL 值

說明:NULL 與任何值的直接比較都為 NULL

1) NULL<>NULL 的返回結果是 NULL,而不是 false

2) NULL=NULL 的返回結果是 NULL,而不是 true

3) NULL<>1 的返回結果是 NULL,而不是 true

注意:

ISNULL (expr) 函數:如果 expr 為 null 返回 1,否則返回 0;ISNULL (expr) = 0 不會排除空值;使用 <> 查詢時,會篩選掉空值和 NULL 值。


NULL 對索引的影響

結論看第 3 點

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

1、給 a 列增加索引 idx_a,a 列可以為 NULL

測試數據總量為 10w 條數據,其中有一條記錄 a 列為 NULL的測試數據

● 查詢所有列

① WHERE 條件中 IS NULL

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

type : ref (非唯一性索引)

key : idx_a

可以看出 WHERE 條件使用 IS NULL ,查詢所有列使用 idx_a ,type 為 ref。

② WHERE 條件中 IS NOT NULL

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

type : ALL

key : (NULL)

可以看出 WHERE 條件使用 IS NOT NULL ,全表掃描,未走索引。


查詢索引列

① WHERE 條件中 IS NULL

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

type : ref (非唯一性索引)

key : idx_a

可以看出 where 條件使用 is null ,查詢所有列使用 idx_a ,type 為 ref

② WHERE 條件中 IS NOT NULL

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

可以看出 where 條件使用 is not null ,查詢所有列使用 idx_a ,type 為 range。


2、給 a 列增加索引 idx_a,a 列可以為 NOT NULL

● 查詢所有列

① WHERE 條件中 IS NULL

無意義,不會使用索引。

Extra 顯示:Impossible WHERE

② WHERE 條件中 IS NOT NULL

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

全表掃描


● 查詢索引列

① WHERE 條件中 IS NULL

無意義,不會使用索引。

Extra 顯示:Impossible WHERE

② WHERE 條件中 IS NOT NULL

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

可以看出 where 條件使用 is not null ,查詢所有列使用 idx_a ,type 為 index。


3、彙總

注:當 a 列為 NOT NULL 且建立 idx_a 索引,無論 WHERE 後時 IS NULL 還是 IS NOT NULL,相當於“脫褲子放屁”,參考價值不大。主要研究當 a 列為 NULL 且建立 idx_a 索引,在MySql 5.7 版本使用 InnoDB 存儲引擎

結論如下:

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)

Python 之 MySql“未解之謎”13--都是 NULL 惹的禍(上)


>>>


分享到:


相關文章: