關於mysql設定varchar 欄位的預設值''和null的區別,以及varchar和char的區別

鐵柱同學發表於2018-05-25

一、背景

      根據業務需求,發現以前的同事在設計表的時候,很多欄位都沒有設定預設值。在mysql5.7版本之後,沒有設定預設值的欄位,在嚴格模式下是很容易報錯的,所以我這邊需要先給每個欄位加上一個預設值。

對於常見的int型別,預設值為0就好,但是對於varchar型別呢,預設值是設定為”還是Null呢?

二、‘’和null的區別

1、佔用空間問題

(1)c語言:

  '\0',這個表示空,需要消耗儲存空間的。
    NULL,則表示連這個\0都沒有。

(2)、mysql:

 1:空值('')是不佔用空間的
    2: MySQL中的NULL其實是佔用空間的。官方文件說明:
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值,而在C語言中空值’不佔用儲存空間。

不僅如此,不使用NULL可以提高索引效率,因為樹形索引結構中將NULL也視作一般資料節點。

2、上面說到了null會影響索引效率

      其實我們在初學mysql的時候,都會看到一段話,那就是mysql建議欄位最好為不要為null,儘量為not null。

原話:

      儘量避免NULL:應該指定列為NOT NULL,除非你想儲存NULL。在MySQL中,含有空值的列很難進行查詢優化。因為它們使得索引、索引的統計資訊以及比較運算更加複雜。你應該用0、一個特殊的值或者一個空串代替空值。

      null會影響索引的統計,一般會預設null為同一個值,這樣這個索引的篩選價值就降低了,影響優化器的判斷。當然也可以調整引數,使得null被認為是不同的值。

結論:也就是說,在設定預設值的時候,儘量不要用Null來當預設值,用空字串(”)會更好一些。帶有null的預設值還是可以走索引的,只是會影響效率。當然,如果確認該欄位不會用到索引的話,也是可以設定為null的

三、在統計時,”和null的區別

這部分建議參考部落格:
MySQL 中NULL和空值的區別

結論

1:在進行count()統計某列的記錄數的時候,如果採用的NULL值,會別系統自動忽略掉,但是空值是會進行統計到其中的。
2: 判斷NULL 用IS NULL 或者 is not null,SQL 語句函式中可以使用ifnull()函式來進行處理,判斷空字元用 =''或者 <>''來進行處理
3: 對於MySQL特殊的注意事項,對於timestamp資料型別,如果往這個資料型別插入的列插入NULL值,則出現的值是當前系統時間。插入空值,則會出現 '0000-00-00 00:00:00'
4:對於空值的判斷到底是使用is null 還是 =''要根據實際業務來進行區分。

四、關於char和varchar的選用

1、定義

眾所周知的,char是定長,而varchar是變長。

      char(M)型別的資料列裡,每個值都佔用M個位元組,如果某個長度小於M,MySQL就會在它的右邊用空格字元補足.(在檢索操作中那些填補出來的空 格字元將被去掉)在varchar(M)型別的資料列裡,每個值只佔用剛好夠用的位元組再加上一個用來記錄其長度的位元組(即總長度為L+1位元組)。

2、哪個更合適

對於MyISAM表,儘量使用Char,對於那些經常需要修改而容易形成碎片的myisam和isam資料表就更是如此,它的缺點就是佔用磁碟空間

   對於InnoDB表,因為它的資料行內部儲存格式對固定長度的資料行和可變長度的資料行不加區分(所有資料行共用一個表頭部分,這個標頭部分存放著指向 各有關資料列的指標),所以使用char型別不見得會比使用varchar型別好。事實上,因為char型別通常要比varchar型別佔用更多的空間, 所以從減少空間佔用量和減少磁碟i/o的角度,使用varchar型別反而更有利

3、結論

1、在確定欄位為短小且定長的時候,用char會好一些

2、在某欄位需要頻繁改寫的時候,用char會好一些(因為varchar每次儲存都要有額外的計算,得到長度等工作,如果一個非常頻繁改變的,那就要有很多的精力用於計算,而這些對於char來說是不需要的。)

3、設計varchar()值的時候,不要一股腦的都用varchar(255):mysql會把表資訊放到記憶體中(查詢第一次後,就快取住 了,linux下很明顯,但windows下似乎沒有,不知道為啥),這時記憶體的申請是按照固定長度來的,如果varchar很大就會有問題。

4、關於varchar(255)和varchar(256) :根據mysql官方文件,varchar(255)需要一個位元組記錄欄位的長度 256以上需要兩個位元組記錄長度。設定長度超過256會有點浪費。

5、因為在業務中使用innoDB多一些,所以儘量還是用varchar()好一些

end

=====================================================================
18年5月26日更新:

      在設定欄位的時候,可以給欄位設定為 not null ,因為 not null 這個概念和預設值是不衝突的。我們在設定預設值為”的時候,雖然避免了null的情況,但是可能存在直接給欄位賦值為null,這樣資料庫中還是會出現null的情況,所以強烈建議都給欄位加上 not null。

就這樣的:

alter table 資料表 modify `欄位名` VARCHAR (255) NOT NULL DEFAULT '';

=======================================================================
18年8月8日更新

      既然上面都說了varchar欄位的預設值最好不要為null,那麼我們平時建表的時候改怎麼寫呢?特別是在phpmyadmin中:

1、如果欄位是int型別,預設為0
2、如果是varchar型別,預設值留空就好。就是定義,然後留空,直接空格就可以。這個時候我們檢視資料表的結構,就會發現該欄位是有預設值的。

相關文章