今天在Facebook的Backend 台灣 (Backend Tw)社團看到板主分享58到家MySQL军规升级版這篇文章,內容是MySQL資料庫的一些設計原則。
關於 第四點-列設計規範 提到 必須把欄位定義為NOT NULL並設預設值,理由如下:
- NULL的列使索引,索引統計,值的比較更複雜,MySQL更難優化。
- NULL需要更多的儲存空間。
- NULL只能採用IS NULL或IS NOT NULL,而在
=
/!=
/IN
/NOT IN
時有大坑。
以上概念的出處為High Performance MySQL, 3rd Edition的Chapter 4: Optimizing Schema and Data Types,第116頁,節錄如下:
Avoid NULL if possible.
A lot of tables include nullable columns even when the application does not need to store NULL (the absence of a value), merely because it’s the default. It’s usually best to specify columns as NOT NULL unless you intend to store NULL in them. It’s harder for MySQL to optimize queries that refer to nullable columns, because they make indexes, index statistics, and value comparisons more complicated. A nullable column uses more storage space and requires special processing inside MySQL. When a nullable column is indexed, it requires an extra byte per entry and can even cause a fixed-size index (such as an index on a single integer column) to be converted to a variable-sized one in MyISAM. The performance improvement from changing NULL columns to NOT NULL is usually small, so don’t make it a priority to find and change them on an existing schema unless you know they are causing problems. However, if you’re planning to index columns, avoid making them nullable if possible. There are exceptions, of course. For example, it’s worth mentioning that InnoDB stores NULL with a single bit, so it can be pretty space-efficient for sparsely populated data. This doesn’t apply to MyISAM, though.
原文是說,把欄位從允許NULL
改為NOT NULL
提升的效能很小,對已存在的schema不用因此特地去修改,除非NULL
可能導致問題。重點應該是只有索引欄位避免允許NULL
,而非所有的欄位都要避免允許NULL
。
原文提到NULL
會占比較多空間是指使用MyISAM引擎的情況,NULL
欄位在InnoDB反而占比較少空間。所以第二點NULL
需要更多的儲存空間的說法不是絕對的。
而關於第三點NULL
欄位在查詢時下WHERE
條件確實是只能用IS NULL
或IS NOT NULL
,而其他的比較運算元則無法判斷NULL
,所以欄位盡可能避免允許NULL
。
所以我的結論是不論MyISAM或InnoDB,索引欄位總是設為NOT NULL
並給定預設值;一般欄位也盡量設為NOT NULL
但非絕對必要,依需求該為NULL
的時候還是可以允許為NULL
。
參考:
沒有留言:
張貼留言