存儲引擎決定了表的類型,而表內存放的數據也要有不一樣的類型,每種數據類型都有本身的寬度,但寬度是可選的html
詳細參考:前端
mysql經常使用數據類型概覽:mysql
#1. 數字: 整型:tinyinit int bigint 小數: float :在位數比較短的狀況下不精準 double :在位數比較長的狀況下不精準 0.000001230123123123 存成:0.000001230000 decimal:(若是用小數,則用推薦使用decimal) 精準 內部原理是以字符串形式去存 #2. 字符串: char(10):簡單粗暴,浪費空間,存取速度快 root存成root000000 varchar:精準,節省空間,存取速度慢 sql優化:建立表時,定長的類型往前放,變長的日後放 好比性別 好比地址或描述信息 >255個字符,超了就把文件路徑存放到數據庫中。 好比圖片,視頻等找一個文件服務器,數據庫中只存路徑或url。 #3. 時間類型: 最經常使用:datetime #4. 枚舉類型與集合類型
一、整數類型sql
整數類型:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT數據庫
做用:存儲年齡,等級,id,各類號碼等服務器
tinyint[(m)] [unsigned] [zerofill] 小整數,數據類型用於保存一些範圍的整數數值範圍: 有符號: -128 ~ 127 無符號: 0 ~ 255 PS: MySQL中無布爾值,使用tinyint(1)構造。 int[(m)][unsigned][zerofill] 整數,數據類型用於保存一些範圍的整數數值範圍: 有符號: -2147483648 ~ 2147483647 無符號: 0 ~ 4294967295 bigint[(m)][unsigned][zerofill] 大整數,數據類型用於保存一些範圍的整數數值範圍: 有符號: -9223372036854775808 ~ 9223372036854775807 無符號: 0 ~ 18446744073709551615
有符號和無符號tinyint 1.tinyint默認爲有符號 mysql> create table t1(x tinyint); #默認爲有符號,即數字前有正負號 mysql> desc t1; mysql> insert into t1 values -> (-129), -> (-128), -> (127), -> (128); mysql> select * from t1; +------+ | x | +------+ | -128 | #-129存成了-128 | -128 | #有符號,最小值爲-128 | 127 | #有符號,最大值127 | 127 | #128存成了127 +------+ 2.設置無符號tinyint mysql> create table t2(x tinyint unsigned); mysql> insert into t2 values -> (-1), -> (0), -> (255), -> (256); mysql> select * from t2; +------+ | x | +------+ | 0 | -1存成了0 | 0 | #無符號,最小值爲0 | 255 | #無符號,最大值爲255 | 255 | #256存成了255 +------+ 有符號和無符號int 1.int默認爲有符號 mysql> create table t3(x int); #默認爲有符號整數 mysql> insert into t3 values -> (-2147483649), -> (-2147483648), -> (2147483647), -> (2147483648); mysql> select * from t3; +-------------+ | x | +-------------+ | -2147483648 | #-2147483649存成了-2147483648 | -2147483648 | #有符號,最小值爲-2147483648 | 2147483647 | #有符號,最大值爲2147483647 | 2147483647 | #2147483648存成了2147483647 +-------------+ 2.設置無符號int mysql> create table t4(x int unsigned); mysql> insert into t4 values -> (-1), -> (0), -> (4294967295), -> (4294967296); mysql> select * from t4; +------------+ | x | +------------+ | 0 | #-1存成了0 | 0 | #無符號,最小值爲0 | 4294967295 | #無符號,最大值爲4294967295 | 4294967295 | #4294967296存成了4294967295 +------------+ 有符號和無符號bigint 1.有符號bigint mysql> create table t6(x bigint); mysql> insert into t5 values -> (-9223372036854775809), -> (-9223372036854775808), -> (9223372036854775807), -> (9223372036854775808); mysql> select * from t5; +----------------------+ | x | +----------------------+ | -9223372036854775808 | | -9223372036854775808 | | 9223372036854775807 | | 9223372036854775807 | +----------------------+ 2.無符號bigint mysql> create table t6(x bigint unsigned); mysql> insert into t6 values -> (-1), -> (0), -> (18446744073709551615), -> (18446744073709551616); mysql> select * from t6; +----------------------+ | x | +----------------------+ | 0 | | 0 | | 18446744073709551615 | | 18446744073709551615 | +----------------------+ 用zerofill測試整數類型的顯示寬度 mysql> create table t7(x int(3) zerofill); mysql> insert into t7 values -> (1), -> (11), -> (111), -> (1111); mysql> select * from t7; +------+ | x | +------+ | 001 | | 011 | | 111 | | 1111 | #超過寬度限制仍然能夠存 +------+
注意:對於整型來講,數據類型後面的寬度並非存儲長度限制,而是顯示限制,假如:int(8),那麼顯示時不夠8位則用0來填充,夠8位則正常顯示,經過zerofill來測試,存儲長度仍是int的4個字節長度。默認的顯示寬度就是可以存儲的最大的數據的長度,好比:int無符號類型,那麼默認的顯示寬度就是int(10),有符號的就是int(11),由於多了一個符號,因此咱們沒有必要指定整數類型的數據,不必指定寬度,由於默認的就可以將你存的原始數據徹底顯示併發
int的存儲寬度是4個Bytes,即32個bit,即2**32 less
無符號最大值爲:4294967296-1運維
有符號最大值:2147483648-1socket
有符號和無符號的最大數字須要的顯示寬度均爲10,而針對有符號的最小值則須要11位才能顯示徹底,因此int類型默認的顯示寬度爲11是很是合理的
最後:整形類型,其實沒有必要指定顯示寬度,使用默認的就ok
說到這裏我想提一下MySQL的mode設置,看我這篇博客:https://www.cnblogs.com/clschao/articles/9962347.html,看完博客應該就能理解MySQL的mode了。
二、浮點型
定點數類型 DEC,等同於DECIMAL
浮點類型:FLOAT DOUBLE
做用:存儲薪資、身高、溫度、體重、體質參數等
1.FLOAT[(M,D)] [UNSIGNED] [ZEROFILL] 定義: 單精度浮點數(非準確小數值),m是整數部分+小數部分的總個數,d是小數點後個數。m最大值爲255,d最大值爲30,例如:float(255,30) 有符號: -3.402823466E+38 to -1.175494351E-38, 1.175494351E-38 to 3.402823466E+38 無符號: 1.175494351E-38 to 3.402823466E+38 精確度: **** 隨着小數的增多,精度變得不許確 **** 2.DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL] 定義: 雙精度浮點數(非準確小數值),m是整數部分+小數部分的總個數,d是小數點後個數。m最大值也爲255,d最大值也爲30 有符號: -1.7976931348623157E+308 to -2.2250738585072014E-308 2.2250738585072014E-308 to 1.7976931348623157E+308 無符號: 2.2250738585072014E-308 to 1.7976931348623157E+308 精確度: ****隨着小數的增多,精度比float要高,但也會變得不許確 **** 3.decimal[(m[,d])] [unsigned] [zerofill] 定義: 準確的小數值,m是整數部分+小數部分的總個數(負號不算),d是小數點後個數。 m最大值爲65,d最大值爲30。比float和double的整數個數少,可是小數位數都是30位 精確度: **** 隨着小數的增多,精度始終準確 **** 對於精確數值計算時須要用此類型 decimal可以存儲精確值的緣由在於其內部按照字符串存儲。 精度從高到低:decimal、double、float decimal精度高,可是整數位數少 float和double精度低,可是整數位數多 float已經知足絕大多數的場景了,可是什麼導彈、航線等要求精度很是高,因此仍是須要按照業務場景自行選擇,若是又要精度高又要整數位數多,那麼你能夠直接用字符串來存。
mysql> create table t1(x float(256,31)); ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30. mysql> create table t1(x float(256,30)); ERROR 1439 (42000): Display width out of range for column 'x' (max = 255) mysql> create table t1(x float(255,30)); #建表成功 Query OK, 0 rows affected (0.02 sec) mysql> create table t2(x double(255,30)); #建表成功 Query OK, 0 rows affected (0.02 sec) mysql> create table t3(x decimal(66,31)); ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30. mysql> create table t3(x decimal(66,30)); ERROR 1426 (42000): Too-big precision 66 specified for 'x'. Maximum is 65. mysql> create table t3(x decimal(65,30)); #建表成功 Query OK, 0 rows affected (0.02 sec) mysql> show tables; +---------------+ | Tables_in_db1 | +---------------+ | t1 | | t2 | | t3 | +---------------+ 3 rows in set (0.00 sec) mysql> insert into t1 values(1.1111111111111111111111111111111); #小數點後31個1 Query OK, 1 row affected (0.01 sec) mysql> insert into t2 values(1.1111111111111111111111111111111); Query OK, 1 row affected (0.00 sec) mysql> insert into t3 values(1.1111111111111111111111111111111); Query OK, 1 row affected, 1 warning (0.01 sec) mysql> select * from t1; #隨着小數的增多,精度開始不許確 +----------------------------------+ | x | +----------------------------------+ | 1.111111164093017600000000000000 | +----------------------------------+ 1 row in set (0.00 sec) mysql> select * from t2; #精度比float要準確點,但隨着小數的增多,一樣變得不許確 +----------------------------------+ | x | +----------------------------------+ | 1.111111111111111200000000000000 | +----------------------------------+ 1 row in set (0.00 sec) mysql> select * from t3; #精度始終準確,d爲30,因而只留了30位小數 +----------------------------------+ | x | +----------------------------------+ | 1.111111111111111111111111111111 | +----------------------------------+ 1 row in set (0.00 sec)
三、位類型(瞭解,不講~~)
BIT(M)能夠用來存放多位二進制數,M範圍從1~64,若是不寫默認爲1位。
注意:對於位字段須要使用函數讀取
bin()顯示爲二進制
hex()顯示爲十六進制
mysql> create table t9(id bit); mysql> desc t9; #bit默認寬度爲1 +-------+--------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+--------+------+-----+---------+-------+ | id | bit(1) | YES | | NULL | | +-------+--------+------+-----+---------+-------+ mysql> insert into t9 values(8); mysql> select * from t9; #直接查看是沒法顯示二進制位的 +------+ | id | +------+ | | +------+ mysql> select bin(id),hex(id) from t9; #須要轉換才能看到 +---------+---------+ | bin(id) | hex(id) | +---------+---------+ | 1 | 1 | +---------+---------+ mysql> alter table t9 modify id bit(5); mysql> insert into t9 values(8); mysql> select bin(id),hex(id) from t9; +---------+---------+ | bin(id) | hex(id) | +---------+---------+ | 1 | 1 | | 1000 | 8 | +---------+---------+
類型:DATE,TIME,DATETIME ,IMESTAMP,YEAR
做用:存儲用戶註冊時間,文章發佈時間,員工入職時間,出生時間,過時時間等
YEAR YYYY(範圍:1901/2155)2018 DATE YYYY-MM-DD(範圍:1000-01-01/9999-12-31)例:2018-01-01 TIME HH:MM:SS(範圍:'-838:59:59'/'838:59:59')例:12:09:32 DATETIME YYYY-MM-DD HH:MM:SS(範圍:1000-01-01 00:00:00/9999-12-31 23:59:59 Y)例: 2018-01-01 12:09:32 TIMESTAMP YYYYMMDD HHMMSS(範圍:1970-01-01 00:00:00/2037 年某時)
year: mysql> create table t10(born_year year); #不管year指定何種寬度,最後都默認是year(4) mysql> insert into t10 values -> (1900), -> (1901), -> (2155), -> (2156); mysql> select * from t10; +-----------+ | born_year | +-----------+ | 0000 | | 1901 | | 2155 | | 0000 | +-----------+ date,time,datetime: mysql> create table t11(d date,t time,dt datetime); mysql> desc t11; +-------+----------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+----------+------+-----+---------+-------+ | d | date | YES | | NULL | | | t | time | YES | | NULL | | | dt | datetime | YES | | NULL | | +-------+----------+------+-----+---------+-------+ mysql> insert into t11 values(now(),now(),now()); mysql> select * from t11; +------------+----------+---------------------+ | d | t | dt | +------------+----------+---------------------+ | 2017-07-25 | 16:26:54 | 2017-07-25 16:26:54 | +------------+----------+---------------------+ timestamp: mysql> create table t12(time timestamp); mysql> insert into t12 values(); mysql> insert into t12 values(null); mysql> select * from t12; +---------------------+ | time | +---------------------+ | 2017-07-25 16:29:17 | | 2017-07-25 16:30:01 | +---------------------+ ============注意啦,注意啦,注意啦=========== 1. 單獨插入時間時,須要以字符串的形式,按照對應的格式插入 2. 插入年份時,儘可能使用4位值 3. 插入兩位年份時,<=69,以20開頭,好比50, 結果2050 >=70,以19開頭,好比71,結果1971 mysql> create table t12(y year); mysql> insert into t12 values -> (50), -> (71); mysql> select * from t12; +------+ | y | +------+ | 2050 | | 1971 | +------+ ============綜合練習=========== mysql> create table student( -> id int, -> name varchar(20), -> born_year year, -> birth date, -> class_time time, -> reg_time datetime); mysql> insert into student values -> (1,'sb1',"1995","1995-11-11","11:11:11","2017-11-11 11:11:11"), -> (2,'sb2',"1997","1997-12-12","12:12:12","2017-12-12 12:12:12"), -> (3,'sb3',"1998","1998-01-01","13:13:13","2017-01-01 13:13:13"); mysql> select * from student; +------+------+-----------+------------+------------+---------------------+ | id | name | born_year | birth | class_time | reg_time | +------+------+-----------+------------+------------+---------------------+ | 1 | sb1 | 1995 | 1995-11-11 | 11:11:11 | 2017-11-11 11:11:11 | | 2 | sb2 | 1997 | 1997-12-12 | 12:12:12 | 2017-12-12 12:12:12 | | 3 | sb3 | 1998 | 1998-01-01 | 13:13:13 | 2017-01-01 13:13:13 | +------+------+-----------+------------+------------+---------------------+
mysql的日期格式對字符串採用的是'放鬆'政策,能夠以字符串的形式插入。
在實際應用的不少場景中,MySQL的這兩種日期類型都可以知足咱們的須要,存儲精度都爲秒,但在某些狀況下,會展示出他們各自的優劣。下面就來總結一下兩種日期類型的區別。 1.DATETIME的日期範圍是1001——9999年,TIMESTAMP的時間範圍是1970——2038年。 2.DATETIME存儲時間與時區無關,TIMESTAMP存儲時間與時區有關,顯示的值也依賴於時區。在mysql服務器,操做系統以及客戶端鏈接都有時區的設置。 3.DATETIME使用8字節的存儲空間,TIMESTAMP的存儲空間爲4字節。所以,TIMESTAMP比DATETIME的空間利用率更高。 4.DATETIME的默認值爲null;TIMESTAMP的字段默認不爲空(not null),默認值爲當前時間(CURRENT_TIMESTAMP),若是不作特殊處理,而且update語句中沒有指定該列的更新值,則默認更新爲當前時間。
工做中通常都用datetime就能夠了。
mysql> create table t1(x datetime not null default now()); # 須要指定傳入空值時默認取當前時間 Query OK, 0 rows affected (0.01 sec) mysql> create table t2(x timestamp); # 無需任何設置,在傳空值的狀況下自動傳入當前時間 Query OK, 0 rows affected (0.02 sec) mysql> insert into t1 values(); Query OK, 1 row affected (0.00 sec) mysql> insert into t2 values(); Query OK, 1 row affected (0.00 sec) mysql> select * from t1; +---------------------+ | x | +---------------------+ | 2018-07-07 01:26:14 | +---------------------+ 1 row in set (0.00 sec) mysql> select * from t2; +---------------------+ | x | +---------------------+ | 2018-07-07 01:26:17 | +---------------------+ 1 row in set (0.00 sec)
類型:char,varchar
做用:名字,信息等等
#官網:https://dev.mysql.com/doc/refman/5.7/en/char.html #注意:char和varchar括號內的參數指的都是字符的長度 #char類型:定長,簡單粗暴,浪費空間,存取速度快 字符長度範圍:0-255(一箇中文是一個字符,是utf8編碼的3個字節) 存儲: 存儲char類型的值時,會往右填充空格來知足長度 例如:指定長度爲10,存>10個字符則報錯(嚴格模式下),存<10個字符則用空格填充直到湊夠10個字符存儲 檢索: 在檢索或者說查詢時,查出的結果會自動刪除尾部的空格,若是你想看到它補全空格以後的內容,除非咱們打開pad_char_to_full_length SQL模式(SET sql_mode = 'strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH';) #varchar類型:變長,精準,節省空間,存取速度慢 字符長度範圍:0-65535(若是大於21845會提示用其餘類型 。mysql行最大限制爲65535字節,字符編碼爲utf-8:https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html) 存儲: varchar類型存儲數據的真實內容,不會用空格填充,若是'ab ',尾部的空格也會被存起來 強調:varchar類型會在真實數據前加1-2Bytes的前綴,該前綴用來表示真實數據的bytes字節數(1-2Bytes最大表示65535個數字,正好符合mysql對row的最大字節限制,即已經足夠使用) 若是真實的數據<255bytes則須要1Bytes的前綴(1Bytes=8bit 2**8最大表示的數字爲255) 若是真實的數據>255bytes則須要2Bytes的前綴(2Bytes=16bit 2**16最大表示的數字爲65535) 檢索: 尾部有空格會保存下來,在檢索或者說查詢時,也會正常顯示包含空格在內的內容
下面咱們來進行一些測試,在測試以前,咱們須要學一下mysql給咱們提供的兩個方法:
length(字段):查看該字段數據的字節長度
char_length(字段):查看該字段數據的字符長度
建立一個t1表,包含一個char類型的字段 create table t1(id int,name char(4)); 超過長度: 嚴格模式下(報錯): mysql> insert into t1 values('xiaoshabi'); ERROR 1406 (22001): Data too long for column 'name' at row 1 非嚴格模式下(警告): mysql> set sql_mode='NO_ENGINE_SUBSTITUTION'; Query OK, 0 rows affected (0.00 sec) mysql> create table t1(id int,name char(4)); Query OK, 0 rows affected (0.40 sec) mysql> insert into t2 values('xiaoshabi'); Query OK, 1 row affected, 1 warning (0.11 sec) 查看一下結果: mysql> select * from t1; +------+------+ | id | name | +------+------+ | 1 | xiao | #只有一個xiao +------+------+ 1 row in set (0.00 sec) varchar類型和上面的效果是同樣的,嚴格模式下也會報錯。 若是沒有超過長度,那麼char類型時mysql會使用空格來補全本身規定的char(4)的4個字符,varchar不會,咱們來作個對比 例如: #再建立一個含有varchar類型的表t2 而後插入幾條和t1裏面相同的數據 mysql>insert into t1 values(2,'a'),(3,'bb'),(4,'ccc'),(5,'d'); mysql>create table t2(id int,name varchar(4)); mysql> insert into t2 values(1,'xiao'),(2,'a'),(3,'bb'),(4,'ccc'),(5,'d'); 查看一下t1表和t2表的內容 mysql> select * from t1; +------+------+ | id | name | +------+------+ | 1 | xiao | | 2 | a | | 3 | bb | | 4 | ccc | | 5 | d | +------+------+ 5 rows in set (0.00 sec) mysql> select * from t2; +------+------+ | id | name | +------+------+ | 1 | xiao | | 2 | a | | 3 | bb | | 4 | ccc | | 5 | d | +------+------+ 5 rows in set (0.00 sec) 好,兩個表裏面數據是同樣的,每一項的數據長度也是同樣的,那麼咱們來驗證一下char的自動空格在後面補全的存儲方式和varchar的不一樣 經過mysql提供的一個char_length()方法來查看一下全部數據的長度 mysql> select char_length(name) from t1; +-------------------+ | char_length(name) | +-------------------+ | 4 | | 1 | | 2 | | 3 | | 1 | +-------------------+ 5 rows in set (0.00 sec) mysql> select char_length(name) from t2; +-------------------+ | char_length(name) | +-------------------+ | 4 | | 1 | | 2 | | 3 | | 1 | +-------------------+ 5 rows in set (0.00 sec) 經過查看結果能夠看到,二者顯示的數據長度是同樣的,不是說好的char會補全嗎,我設置的字段是char(4),那麼長度應該都是4纔對啊?這是由於mysql在你查詢的時候自動幫你把結果裏面的空格去掉了,若是咱們想看到它存儲數據的真實長度,須要設置mysql的模式,經過一個叫作PAD_CHAR_TO_FULL_LENGTH的模式,就能夠看到了,因此咱們把這個模式加到sql_mode裏面: mysql> set sql_mode='PAD_CHAR_TO_FULL_LENGTH'; Query OK, 0 rows affected (0.00 sec) 而後咱們在查看一下t1和t2數據的長度: mysql> select char_length(name) from t1; +-------------------+ | char_length(name) | +-------------------+ | 4 | | 4 | | 4 | | 4 | | 4 | +-------------------+ 5 rows in set (0.00 sec) mysql> select char_length(name) from t2; +-------------------+ | char_length(name) | +-------------------+ | 4 | | 1 | | 2 | | 3 | | 1 | +-------------------+ 5 rows in set (0.00 sec) 經過結果能夠看到,char類型的數據長度都是4,這下看到了二者的不一樣了吧,至於爲何mysql會這樣搞,咱們後面有解釋的,先看現象就能夠啦。 如今咱們再來看一個問題,就是當你設置的類型爲char的時候,咱們經過where條件來查詢的時候會有一個什麼現象: mysql> select * from t1 where name='a'; +------+------+ | id | name | +------+------+ | 2 | a | +------+------+ 1 row in set (0.00 sec) ok,結果沒問題,咱們在where後面的a後面加一下空格再來試試: mysql> select * from t1 where name='a '; +------+------+ | id | name | +------+------+ | 2 | a | +------+------+ 1 row in set (0.00 sec) ok,能查到,再多加一些空格試試,加6個空格,超過了設置的char(4)的4: mysql> select * from t1 where name='a '; +------+------+ | id | name | +------+------+ | 2 | a | +------+------+ 1 row in set (0.00 sec) ok,也是沒問題的 總結:經過>,=,>=,<,<=做爲where的查詢條件的時候,char類型字段的查詢是沒問題的。 可是,當咱們將where後面的比較符號改成like的時候,(like是模糊匹配的意思,咱們前面見過,show variables like '%char%';來查看mysql字符集的時候用過) 其中%的意思是匹配任意字符(0到多個字符均可以匹配到),還有一個符號是_(匹配1個字符),這兩個字符其實就像咱們學的正則匹配裏面的通配符,那麼咱們經過這些符號進行一下模糊查詢,看一下,char類型進行模糊匹配的時候,是否還能行,看例子: mysql> select * from t1 where name like 'a'; Empty set (0.00 sec) 發現啥也沒查到,由於char存儲的數據是4個字符長度的,不滿4個是以空格來補全的,你在like後面就只寫了一個'a',是沒法查到的。 咱們試一下上面的通配符來查詢: mysql> select * from t1 where name like 'a%'; +------+------+ | id | name | +------+------+ | 2 | a | +------+------+ 1 row in set (0.00 sec) 這樣就能看到查詢結果了 試一下_是否是匹配1個字符: mysql> select * from t1 where name like 'a_'; Empty set (0.00 sec) 發現一個_果真不行,咱們試試三個_。 mysql> select * from t1 where name like 'a___'; +------+------+ | id | name | +------+------+ | 2 | a | +------+------+ 1 row in set (0.00 sec) 發現果真能行,一個_最多匹配1個任意字符。 若是多寫了幾個_呢? mysql> select * from t1 where name like 'a_____'; Empty set (0.00 sec) 查不到結果,說明_匹配的是1個字符,但不是0-1個字符。
測試結果總結:
針對char類型,mysql在存儲的時候會將不足規定長度的數據使用後面(右邊補全)補充空格的形式進行補全,而後存放到硬盤中,可是在讀取或者使用的時候會自動去掉它給你補全的空格內容,由於這些空格並非咱們本身存儲的數據,因此對咱們使用者來講是無用的。
char和varchar性能對比:
以char(5)和varchar(5)來比較,加入我要存三我的名:sb,ssb1,ssbb2
char:
優勢:簡單粗暴,無論你是多長的數據,我就按照規定的長度來存,5個5個的存,三我的名就會相似這種存儲:sb ssb1 ssbb2,中間是空格補全,取數據的時候5個5個的取,簡單粗暴速度快
缺點:貌似浪費空間,而且咱們未來存儲的數據的長度可能會良莠不齊
varchar:
varchar類型不定長存儲數據,更爲精簡和節省空間
例如存上面三我的名的時候相似因而這樣的:sbssb1ssbb2,連着的,若是這樣存,請問這三我的名你還怎麼取出來,你知道取多長能取出第一個嗎?(超哥,我能看出來啊,那我只想說:滾犢子!)
不知道從哪開始從哪結束,遇到這樣的問題,你會想到怎麼解決呢?還記的嗎?想一想?socket?tcp?struct?把數據長度做爲消息頭。
因此,varchar在存數據的時候,會在每一個數據前面加上一個頭,這個頭是1-2個bytes的數據,這個數據指的是後面跟着的這個數據的長度,1bytes能表示28=256,兩個bytes表示216=65536,能表示0-65535的數字,因此varchar在存儲的時候是這樣的:1bytes+sb+1bytes+ssb1+1bytes+ssbb2,因此存的時候會比較麻煩,致使效率比char慢,取的時候也慢,先拿長度,再取數據。
優勢:節省了一些硬盤空間,一個acsii碼的字符用一個bytes長度就能表示,可是也並不必定比char省,看一下官網給出的一個表格對比數據,當你存的數據正好是你規定的字段長度的時候,varchar反而佔用的空間比char要多。
Value | CHAR(4) |
Storage Required | VARCHAR(4) |
Storage Required |
---|---|---|---|---|
'' |
' ' |
4 bytes | '' |
1 byte |
'ab' |
'ab ' |
4 bytes | 'ab' |
3 bytes |
'abcd' |
'abcd' |
4 bytes | 'abcd' |
5 bytes |
'abcdefgh' |
'abcd' |
4 bytes | 'abcd' |
5 bytes |
缺點:存取速度都慢
總結:
因此須要根據業務需求來選擇用哪一種類型來存
其實在多數的用戶量少的工做場景中char和varchar效率差異不是很大,最起碼給用戶的感知不是很大,而且其實軟件級別的慢遠比不上硬件級別的慢,因此大家公司的運維發現項目慢的時候會加內存、換nb的硬盤,項目的效率提高的會不少,可是咱們做爲專業人士,咱們應該提出來這樣的技術點來提升效率。
可是對於InnoDB數據表,內部的行存儲格式沒有區分固定長度和可變長度列(全部數據行都使用指向數據列值的頭指針),所以在本質上,使用固定長度的CHAR列不必定比使用可變長度VARCHAR列性能要好。於是,主要的性能因素是數據行使用的存儲總量。因爲CHAR平均佔用的空間多於VARCHAR,所以使用VARCHAR來最小化須要處理的數據行的存儲總量和磁盤I/O是比較好的。
因此啊,兩個選哪一個均可以,若是是大型併發項目,追求高性能的時候,須要結合大家服務器的硬件環境來進行測試,看一下char和varchar哪一個更好,這也能算一個優化的點吧~~~~
#官網:https://dev.mysql.com/doc/refman/5.7/en/char.html CHAR 和 VARCHAR 是最常使用的兩種字符串類型。 通常來講 CHAR(N)用來保存固定長度的字符串,對於 CHAR 類型,N 的範圍 爲 0 ~ 255 VARCHAR(N)用來保存變長字符類型,對於 VARCHAR 類型,N 的範圍爲 0 ~ 65 535 CHAR(N)和 VARCHAR(N) 中的 N 都表明字符長度,而非字節長度。 ps:對於 MySQL 4.1 以前的版本,如 MySQL 3.23 和 MySQL 4.0,CHAR(N)和 VARCHAR (N)中的 N 表明字節長度。 #CHAR類型 對於 CHAR 類型的字符串,MySQL 數據庫會自動對存儲列的右邊進行填充(Right Padded)操做,直到字符串達到指定的長度 N。而在讀取該列時,MySQL 數據庫會自動將 填充的字符刪除。有一種狀況例外,那就是顯式地將 SQL_MODE 設置爲 PAD_CHAR_TO_ FULL_LENGTH,例如: mysql> CREATE TABLE t ( a CHAR(10)); Query OK, 0 rows affected (0.03 sec) mysql> INSERT INTO t SELECT 'abc'; Query OK, 1 row affected (0.03 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> SELECT a,HEX(a),LENGTH(a) FROM t\G; *************************** 1. row *************************** a: abc HEX(a): 616263 LENGTH (a): 3 1 row in set (0.00 sec) mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT a,HEX(a),LENGTH(a) FROM t\G; *************************** 1. row *************************** a: abc HEX(a): 61626320202020202020 LENGTH (a): 10 1 row in set (0.00 sec) 在上述這個例子中,先建立了一張表 t,a 列的類型爲 CHAR(10)。而後經過 INSERT語句插入值「abc」,由於 a 列的類型爲 CHAR 型,因此會自動在後面填充空字符串,使其長 度爲 10。接下來在經過 SELECT 語句取出數據時會將 a 列右填充的空字符移除,從而獲得 值「abc」。經過 LENGTH 函數看到 a 列的字符長度爲 3 而非 10。 接着咱們將 SQL_MODE 顯式地設置爲 PAD_CHAR_TO_FULL_LENGTH。這時再經過 SELECT 語句進行查詢時,獲得的結果是「abc 」,abc 右邊有 7 個填充字符 0x20,並通 過 HEX 函數獲得了驗證。此次 LENGTH 函數返回的長度爲 10。須要注意的是,LENGTH 函數返回的是字節長度,而不是字符長度。對於多字節字符集,CHAR(N)長度的列最多 可佔用的字節數爲該字符集單字符最大佔用字節數 *N。例如,對於 utf8 下,CHAR(10)最 多可能佔用 30 個字節。經過對多字節字符串使用 CHAR_LENGTH 函數和 LENGTH 函數, 能夠發現二者的不一樣,示例以下: mysql> SET NAMES gbk; Query OK, 0 rows affected (0.03 sec) mysql> SELECT @a:='MySQL 技術內幕 '; Query OK, 0 rows affected (0.03 sec) mysql> SELECT @a,HEX(@a),LENGTH(@a),CHAR_LENGTH(@a)\G; ***************************** 1. row **************************** a: MySQL 技術內幕 HEX(a): 4D7953514CBCBCCAF5C4DAC4BB LENGTH (a): 13 CHAR_LENGTH(a): 9 1 row in set (0.00 sec) 變 量 @ a 是 g b k 字 符 集 的 字 符 串 類 型 , 值 爲 「 M y S Q L 技 術 內 幕 」, 十 六 進 制 爲 0x4D7953514CBCBCCAF5C4DAC4BB,LENGTH 函數返回 13,即該字符串佔用 13 字節, 由於 gbk 字符集中的中文字符佔用兩個字節,所以一共佔用 13 字節。CHAR_LENGTH 函數 返回 9,很顯然該字符長度爲 9。 #VARCHAR類型 VARCHAR 類型存儲變長字段的字符類型,與 CHAR 類型不一樣的是,其存儲時須要在 前綴長度列表加上實際存儲的字符,該字符佔用 1 ~ 2 字節的空間。當存儲的字符串長度小 於 255 字節時,其須要 1 字節的空間,當大於 255 字節時,須要 2 字節的空間。因此,對 於單字節的 latin1 來講,CHAR(10)和 VARCHAR(10)最大佔用的存儲空間是不一樣的, CHAR(10)佔用 10 個字節這是毫無疑問的,而 VARCHAR(10)的最大佔用空間數是 11 字節,由於其須要 1 字節來存放字符長度。 ------------------------------------------------- 注意 對於有些多字節的字符集類型,其 CHAR 和 VARCHAR 在存儲方法上是同樣的,一樣 須要爲長度列表加上字符串的值。對於 GBK 和 UTF-8 這些字符類型,其有些字符是以 1 字節 存放的,有些字符是按 2 或 3 字節存放的,所以一樣須要 1 ~ 2 字節的空間來存儲字符的長 度。 ------------------------------------------------- 雖然 CHAR 和 VARCHAR 的存儲方式不太相同,可是對於兩個字符串的比較,都只比 較其值,忽略 CHAR 值存在的右填充,即便將 SQL _MODE 設置爲 PAD_CHAR_TO_FULL_ LENGTH 也同樣,例如: mysql> CREATE TABLE t ( a CHAR(10), b VARCHAR(10)); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO t SELECT 'a','a'; Query OK, 1 row affected (0.00 sec) Records: 1 Duplicates: 0 Warnings: 0 mysql> SELECT a=b FROM t\G; *************************** 1. row *************************** a=b: 1 1 row in set (0.00 sec) mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT a=b FROM t\G; *************************** 1. row *************************** a=b: 1 1 row in set (0.00 sec)
其餘的字符串類型:BINARY、VARBINARY、BLOB、TEXT
BINARY 和 VARBINARY 相似於 CHAR 和 VARCHAR,不一樣的是它們包含二進制字符串而不要非二進制字符串。也就是說,它們包含字節字符串而不是字符字符串。這說明它們沒有字符集,而且排序和比較基於列值字節的數值值。 BLOB 是一個二進制大對象,能夠容納可變數量的數據。有 4 種 BLOB 類型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它們區別在於可容納存儲範圍不一樣。 有 4 種 TEXT 類型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。對應的這 4 種 BLOB 類型,可存儲的最大長度不一樣,可根據實際狀況選擇。 BLOB: 1._BLOB和_text存儲方式不一樣,_TEXT以文本方式存儲,英文存儲區分大小寫,而_Blob是以二進制方式存儲,不分大小寫。 2._BLOB存儲的數據只能總體讀出。 3._TEXT能夠指定字符集,_BLO不用指定字符集。
字段的值只能在給定範圍中選擇,如單選框,多選框,若是你在應用程序或者前端不作選項限制,在MySQL的字段裏面也能作限制
enum 單選 只能在給定的範圍內選一個值,如性別 sex 男male/女female
set 多選 在給定的範圍內能夠選擇一個或一個以上的值(愛好1,愛好2,愛好3...)
枚舉類型(enum) An ENUM column can have a maximum of 65,535 distinct elements. (The practical limit is less than 3000.) 示例: CREATE TABLE shirts ( name VARCHAR(40), size ENUM('x-small', 'small', 'medium', 'large', 'x-large') ); INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),('polo shirt','small'); 集合類型(set) A SET column can have a maximum of 64 distinct members. 示例: CREATE TABLE myset (col SET('a', 'b', 'c', 'd')); INSERT INTO myset (col) VALUES ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
mysql> create table consumer( -> name varchar(50), -> sex enum('male','female'), -> level enum('vip1','vip2','vip3','vip4','vip5'), #在指定範圍內,多選一 -> hobby set('play','music','read','study') #在指定範圍內,多選多 -> ); mysql> insert into consumer values -> ('xiaogui','male','vip5','read,study'), -> ('taibai','female','vip1','girl'); mysql> select * from consumer; +------+--------+-------+------------+ | name | sex | level | hobby | +------+--------+-------+------------+ | xiaogui | male | vip5 | read,study | | taibai | female | vip1 | | +------+--------+-------+------------+