數(shù)據(jù)庫(kù)類(lèi)型可分為層次型、網(wǎng)狀型和關(guān)系型。
目前累計(jì)服務(wù)客戶(hù)近千家,積累了豐富的產(chǎn)品開(kāi)發(fā)及服務(wù)經(jīng)驗(yàn)。以網(wǎng)站設(shè)計(jì)水平和技術(shù)實(shí)力,樹(shù)立企業(yè)形象,為客戶(hù)提供網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè)、網(wǎng)站策劃、網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)絡(luò)營(yíng)銷(xiāo)、VI設(shè)計(jì)、網(wǎng)站改版、漏洞修補(bǔ)等服務(wù)。成都創(chuàng)新互聯(lián)始終以務(wù)實(shí)、誠(chéng)信為根本,不斷創(chuàng)新和提高建站品質(zhì),通過(guò)對(duì)領(lǐng)先技術(shù)的掌握、對(duì)創(chuàng)意設(shè)計(jì)的研究、對(duì)客戶(hù)形象的視覺(jué)傳遞、對(duì)應(yīng)用系統(tǒng)的結(jié)合,為客戶(hù)提供更好的一站式互聯(lián)網(wǎng)解決方案,攜手廣大客戶(hù),共同發(fā)展進(jìn)步。
層次型數(shù)據(jù)庫(kù)是把數(shù)據(jù)根據(jù)層次構(gòu)造(樹(shù)結(jié)構(gòu))的方法呈現(xiàn);網(wǎng)狀型數(shù)據(jù)庫(kù)是采用網(wǎng)狀原理和方法,以網(wǎng)狀數(shù)據(jù)模型為基礎(chǔ)建立的數(shù)據(jù)庫(kù);關(guān)系型數(shù)據(jù)庫(kù)是指采用了關(guān)系模型來(lái)組織數(shù)據(jù)的數(shù)據(jù)庫(kù)。
數(shù)據(jù)庫(kù)的作用
1、實(shí)現(xiàn)數(shù)據(jù)共享:數(shù)據(jù)共享包含所有用戶(hù)可同時(shí)存取數(shù)據(jù)庫(kù)中的數(shù)據(jù),也包括用戶(hù)可以用各種方式通過(guò)接口使用數(shù)據(jù)庫(kù),并提供數(shù)據(jù)共享。
2、減少數(shù)據(jù)的冗余度:同文件系統(tǒng)相比,由于數(shù)據(jù)庫(kù)實(shí)現(xiàn)了數(shù)據(jù)共享,從而避免了用戶(hù)各自建立應(yīng)用文件。減少了大量重復(fù)數(shù)據(jù),減少了數(shù)據(jù)冗余,維護(hù)了數(shù)據(jù)的一致性。
3、保持?jǐn)?shù)據(jù)的獨(dú)立性:數(shù)據(jù)的獨(dú)立性包括邏輯獨(dú)立性(數(shù)據(jù)庫(kù)中數(shù)據(jù)庫(kù)的邏輯結(jié)構(gòu)和應(yīng)用程序相互獨(dú)立)和物理獨(dú)立性(數(shù)據(jù)物理結(jié)構(gòu)的變化不影響數(shù)據(jù)的邏輯結(jié)構(gòu))。
4、數(shù)據(jù)實(shí)現(xiàn)集中控制:文件管理方式中,數(shù)據(jù)處于一種分散的狀態(tài),不同的用戶(hù)或同一用戶(hù)在不同處理中其文件之間毫無(wú)關(guān)系。利用數(shù)據(jù)庫(kù)可對(duì)數(shù)據(jù)進(jìn)行集中控制和管理,并通過(guò)數(shù)據(jù)模型表示各種數(shù)據(jù)的組織以及數(shù)據(jù)間的聯(lián)系。
MySQL 數(shù)據(jù)類(lèi)型細(xì)分下來(lái),大概有以下幾類(lèi):
數(shù)值,典型代表為 tinyint,int,bigint
浮點(diǎn)/定點(diǎn),典型代表為 float,double,decimal 以及相關(guān)的同義詞
字符串,典型代表為 char,varchar
時(shí)間日期,典型代表為 date,datetime,time,timestamp
二進(jìn)制,典型代表為 binary,varbinary
位類(lèi)型
枚舉類(lèi)型
集合類(lèi)型
以下內(nèi)容,我們?cè)诹硪黄恼陆榻B
大對(duì)象,比如 text,blob
json 文檔類(lèi)型
一、數(shù)值類(lèi)型(不是數(shù)據(jù)類(lèi)型,別看錯(cuò)了)如果用來(lái)存放整數(shù),根據(jù)范圍的不同,選擇不同的類(lèi)型。
以上是幾個(gè)整數(shù)選型的例子。整數(shù)的應(yīng)用范圍最廣泛,可以用來(lái)存儲(chǔ)數(shù)字,也可以用來(lái)存儲(chǔ)時(shí)間戳,還可以用來(lái)存儲(chǔ)其他類(lèi)型轉(zhuǎn)換為數(shù)字后的編碼,如 IPv4 等。示例 1用 int32 來(lái)存放 IPv4 地址,比單純用字符串節(jié)省空間。表 x1,字段 ipaddr,利用函數(shù) inet_aton,檢索的話用函數(shù) inet_ntoa。
查看磁盤(pán)空間占用,t3 占用最大,t1 占用最小。所以說(shuō)如果整數(shù)存儲(chǔ)范圍有固定上限,并且未來(lái)也沒(méi)有必要擴(kuò)容的話,建議選擇最小的類(lèi)型,當(dāng)然了對(duì)其他類(lèi)型也適用。root@ytt-pc:/var/lib/mysql/3305/ytt# ls -sihl總用量 3.0G3541825 861M -rw-r----- 1 mysql mysql 860M 12月 10 11:36 t1.ibd3541820 989M -rw-r----- 1 mysql mysql 988M 12月 10 11:38 t2.ibd3541823 1.2G -rw-r----- 1 mysql mysql 1.2G 12月 10 11:39 t3.ibd
二、浮點(diǎn)數(shù) / 定點(diǎn)數(shù)先說(shuō)?浮點(diǎn)數(shù),float 和 double 都代表浮點(diǎn)數(shù),區(qū)別簡(jiǎn)單記就是 float 默認(rèn)占 4 Byte。float(p) 中的 p 代表整數(shù)位最小精度。如果 p 24 則直接轉(zhuǎn)換為 double,占 8 Byte。p 最大值為 53,但最大值存在計(jì)算不精確的問(wèn)題。再說(shuō)?定點(diǎn)數(shù),包括 decimal 以及同義詞 numeric,定點(diǎn)數(shù)的整數(shù)位和小數(shù)位分別存儲(chǔ),有效精度最大不能超過(guò) 65。所以區(qū)別于 float 的在于精確存儲(chǔ),必須需要精確存儲(chǔ)或者精確計(jì)算的最好定義為 decimal 即可。示例 3創(chuàng)建一張表 y1,分別給字段 f1,f2,f3 不同的類(lèi)型。mysql-(ytt/3305)-create table y1(f1 float,f2 double,f3 decimal(10,2));Query OK, 0 rows affected (0.03 sec)
三、字符類(lèi)型字符類(lèi)型和整形一樣,用途也很廣。用來(lái)存儲(chǔ)字符、字符串、MySQL 所有未知的類(lèi)型??梢院?jiǎn)單說(shuō)是萬(wàn)能類(lèi)型!
char(10) 代表最大支持 10 個(gè)字符存儲(chǔ),varhar(10) 雖然和 char(10) 可存儲(chǔ)的字符數(shù)一樣多,不同的是 varchar 類(lèi)型存儲(chǔ)的是實(shí)際大小,char 存儲(chǔ)的理論固定大小。具體的字節(jié)數(shù)和字符集相關(guān)。示例 4例如下面表 t4 ,兩個(gè)字段 c1,c2,分別為 char 和 varchar。mysql-(ytt/3305)-create table t4 (c1 char(20),c2 varchar(20));Query OK, 0 rows affected (0.02 sec)
所以在 char 和 varchar 選型上,要注意看是否合適的取值范圍。比如固定長(zhǎng)度的值,肯定要選擇 char;不確定的值,則選擇 varchar。
四、日期類(lèi)型日期類(lèi)型包含了 date,time,datetime,timestamp,以及 year。year 占 1 Byte,date 占 3 Byte?!?/p>
time,timestamp,datetime 在不包含小數(shù)位時(shí)分別占用 3 Byte,4 Byte,8 Byte;小數(shù)位部分另外計(jì)算磁盤(pán)占用,見(jiàn)下面表格。
請(qǐng)點(diǎn)擊輸入圖片描述
注意:timestamp 代表的時(shí)間戳是一個(gè) int32 存儲(chǔ)的整數(shù),取值范圍為 '1970-01-01 00:00:01.000000' 到 '2038-01-19 03:14:07.999999';datetime 取值范圍為 '1000-01-01 00:00:00.000000' 到 '9999-12-31 23:59:59.999999'。?
綜上所述,日期這塊類(lèi)型的選擇遵循以下原則:
1. 如果時(shí)間有可能超過(guò)時(shí)間戳范圍,優(yōu)先選擇 datetime。2. 如果需要單獨(dú)獲取年份值,比如按照年來(lái)分區(qū),按照年來(lái)檢索等,最好在表中添加一個(gè) year 類(lèi)型來(lái)參與。3. 如果需要單獨(dú)獲取日期或者時(shí)間,最好是單獨(dú)存放,而不是簡(jiǎn)單的用 datetime 或者 timestamp。后面檢索時(shí),再加函數(shù)過(guò)濾,以免后期增加 SQL 編寫(xiě)帶來(lái)額外消耗。
4. 如果有保存毫秒類(lèi)似的需求,最好是用時(shí)間類(lèi)型自己的特性,不要直接用字符類(lèi)型來(lái)代替。MySQL 內(nèi)部的類(lèi)型轉(zhuǎn)換對(duì)資源額外的消耗也是需要考慮的。
示例 5
建立表 t5,對(duì)這些可能需要的字段全部分離開(kāi),這樣以后寫(xiě) SQL 語(yǔ)句的時(shí)候就很容易了。
當(dāng)然了,這種情形占用額外的磁盤(pán)空間。如果想在易用性與空間占用量大這兩點(diǎn)來(lái)折中,可以用 MySQL 的虛擬列來(lái)實(shí)時(shí)計(jì)算。比如假設(shè) c5 字段不存在,想要得到 c5 的結(jié)果。mysql-(ytt/3305)-alter table t5 drop c5, add c5 year generated always as (year(c1)) virtual;Query OK, 1 row affected (2.46 sec)Records: 1 ?Duplicates: 0 ?Warnings: 0
五、二進(jìn)制類(lèi)型
binary 和 varbinary 對(duì)應(yīng)了 char 和 varchar 的二進(jìn)制存儲(chǔ),相關(guān)的特性都一樣。不同的有以下幾點(diǎn):
binary(10)/varbinary(10) 代表的不是字符個(gè)數(shù),而是字節(jié)數(shù)。
行結(jié)束符不一樣。char 的行結(jié)束符是 \0,binary 的行結(jié)束符是 0x00。
由于是二進(jìn)制存儲(chǔ),所以字符編碼以及排序規(guī)則這類(lèi)就直接無(wú)效了。
示例 6
來(lái)看這個(gè) binary 存取的簡(jiǎn)單示例,還是之前的變量 @a。
切記!這里要提前計(jì)算好 @a 占用的字節(jié)數(shù),以防存儲(chǔ)溢出。
六、位類(lèi)型
bit 為 MySQL 里存儲(chǔ)比特位的類(lèi)型,最大支持 64 比特位, 直接以二進(jìn)制方式存儲(chǔ),一般用來(lái)存儲(chǔ)狀態(tài)類(lèi)的信息。比如,性別,真假等。具有以下特性:
1. 對(duì)于 bit(8) 如果單純存放 1 位,左邊以 0 填充 00000001。2. 查詢(xún)時(shí)可以直接十進(jìn)制來(lái)過(guò)濾數(shù)據(jù)。3. 如果此字段加上索引,MySQL 不會(huì)自己做類(lèi)型轉(zhuǎn)換,只能用二進(jìn)制來(lái)過(guò)濾。
示例 7
創(chuàng)建表 c1, 字段性別定義一個(gè)比特位。mysql-(ytt/3305)-create table c1(gender bit(1));Query OK, 0 rows affected (0.02 sec)
mysql-(ytt/3305)-select cast(gender as unsigned) ?'f1' from c1;+------+| f1 ? |+------+| ? ?0 || ? ?1 |+------+2 rows in set (0.00 sec)
過(guò)濾數(shù)據(jù)也一樣,二進(jìn)制或者直接十進(jìn)制都行。mysql-(ytt/3305)-select conv(gender,16,10) as gender \???- from c1 where gender = b'1';?+--------+| gender |+--------+| 1??????|+--------+1 row in set (0.00 sec)????mysql-(ytt/3305)-select conv(gender,16,10) as gender \????- from c1 where gender = '1';+--------+| gender |+--------+| 1??????|+--------+1 row in set (0.00 sec)
其實(shí)這樣的場(chǎng)景,也可以定義為 char(0),這也是類(lèi)似于 bit 非常優(yōu)化的一種用法。
mysql-(ytt/3305)-create table c2(gender char(0));Query OK, 0 rows affected (0.03 sec)
那現(xiàn)在我給表 c1 簡(jiǎn)單的造點(diǎn)測(cè)試數(shù)據(jù)。
mysql-(ytt/3305)-select count(*) from c1;+----------+| count(*) |+----------+| 33554432 |+----------+1 row in set (1.37 sec)
把 c1 的數(shù)據(jù)全部插入 c2。
mysql-(ytt/3305)-insert into c2 select if(gender = 0,'',null) from c1;Query OK, 33554432 rows affected (2 min 18.80 sec)Records: 33554432 ?Duplicates: 0 ?Warnings: 0
兩張表的磁盤(pán)占用差不多。root@ytt-pc:/var/lib/mysql/3305/ytt# ls -sihl總用量 1.9G4085684 933M -rw-r----- 1 mysql mysql 932M 12月 11 10:16 c1.ibd4082686 917M -rw-r----- 1 mysql mysql 916M 12月 11 10:22 c2.ibd
檢索方式稍微有些不同,不過(guò)效率也差不多。所以說(shuō),字符類(lèi)型不愧為萬(wàn)能類(lèi)型。
七、枚舉類(lèi)型
枚舉類(lèi)型,也即 enum。適合提前規(guī)劃好了所有已經(jīng)知道的值,且未來(lái)最好不要加新值的情形。枚舉類(lèi)型有以下特性:
1. 最大占用 2 Byte。2. 最大支持 65535 個(gè)不同元素。3. MySQL 后臺(tái)存儲(chǔ)以下標(biāo)的方式,也就是 tinyint 或者 smallint 的方式,下標(biāo)從 1 開(kāi)始。4. 排序時(shí)按照下標(biāo)排序,而不是按照里面元素的數(shù)據(jù)類(lèi)型。所以這點(diǎn)要格外注意。
示例 8
創(chuàng)建表 t7。mysql-(ytt/3305)-create table t7(c1 enum('mysql','oracle','dble','postgresql','mongodb','redis','db2','sql server'));Query OK, 0 rows affected (0.03 sec)
八、集合類(lèi)型
集合類(lèi)型 SET 和枚舉類(lèi)似,也是得提前知道有多少個(gè)元素。SET 有以下特點(diǎn):
1. 最大占用 8 Byte,int64。2. 內(nèi)部以二進(jìn)制位的方式存儲(chǔ),對(duì)應(yīng)的下標(biāo)如果以十進(jìn)制來(lái)看,就分別為 1,2,4,8,...,pow(2,63)。3. 最大支持 64 個(gè)不同的元素,重復(fù)元素的插入,取出來(lái)直接去重。4. 元素之間可以組合插入,比如下標(biāo)為 1 和 2 的可以一起插入,直接插入 3 即可。
示例 9
定義表 c7 字段 c1 為 set 類(lèi)型,包含了 8 個(gè)值,也就是下表最大為 pow(2,7)。
mysql-(ytt/3305)-create table c7(c1 set('mysql','oracle','dble','postgresql','mongodb','redis','db2','sql server'));Query OK, 0 rows affected (0.02 sec)
插入 1 到 128 的所有組合。
mysql-(ytt/3305)-INSERT INTO c7WITH RECURSIVE ytt_number (cnt) AS ( ? ? ? ?SELECT 1 AS cnt ? ? ? ?UNION ALL ? ? ? ?SELECT cnt + 1 ? ? ? ?FROM ytt_number ? ? ? ?WHERE cnt pow(2, 7) ? ?)SELECT *FROM ytt_number;Query OK, 128 rows affected (0.01 sec)Records: 128 ?Duplicates: 0 ?Warnings: 0
九、數(shù)據(jù)類(lèi)型在存儲(chǔ)函數(shù)中的用法
函數(shù)里除了顯式聲明的變量外,默認(rèn) session 變量的數(shù)據(jù)類(lèi)型很弱,隨著給定值的不同隨意轉(zhuǎn)換。
示例 10
定義一個(gè)函數(shù),返回兩個(gè)給定參數(shù)的乘積。定義里有兩個(gè)變量,一個(gè)是 v_tmp 顯式定義為 int64,另外一個(gè) @vresult 隨著給定值的類(lèi)型隨意變換類(lèi)型。
簡(jiǎn)單調(diào)用下。
mysql-(ytt/3305)-select ytt_sample_data_type(1111,222) 'result';+--------------------------+| result ? ? ? ? ? ? ? ? ? |+--------------------------+| The result is: '246642'. |+--------------------------+1 row in set (0.00 sec)
總結(jié)
本篇把 MySQL 基本的數(shù)據(jù)類(lèi)型做了簡(jiǎn)單的介紹,并且用了一些容易理解的示例來(lái)梳理這些類(lèi)型。我們?cè)趯?shí)際場(chǎng)景中,建議選擇適合最合適的類(lèi)型,不建議所有數(shù)據(jù)類(lèi)型簡(jiǎn)單的最大化原則。比如能用 varchar(100),不用 varchar(1000)。
Mysql支持的多種數(shù)據(jù)類(lèi)型主要有:數(shù)值數(shù)據(jù)類(lèi)型、日期/時(shí)間類(lèi)型、字符串類(lèi)型。?
1.整數(shù)數(shù)據(jù)類(lèi)型及其取值范圍:
類(lèi)型
說(shuō)明
存儲(chǔ)需求(取值范圍)
tinyint ? ?很小整數(shù) ? ?1字節(jié)([0~255]、[-128~127]); 255=2^8-1;127=2^7-1 ?
smallint ? ?小整數(shù) ? ?2字節(jié)(0~65535、-32768~32767) ;65535=2^16-1 ?
mediumint ? ?中等 ? ?3字節(jié)(0~16777215) ;16777215=2^24-1 ?
int(integer) ? ?普通 ? ?4字節(jié)(0~4294967295) ;4294967295=2^32-1 ?
bigint ? ?大整數(shù) ? ?8字節(jié)(0~18446744073709551615);18446744073709551615=2^64-1 ?
浮點(diǎn)數(shù)定點(diǎn)數(shù):
類(lèi)型名稱(chēng)
說(shuō)明
存儲(chǔ)需求
float ? ?單精度浮點(diǎn)數(shù) ? ?4字節(jié) ?
double ? ?雙精度浮點(diǎn)數(shù) ? ?8字節(jié) ?
decimal ? ?壓縮的“嚴(yán)格”定點(diǎn)數(shù) ? ?M+2字節(jié) ?
注:定點(diǎn)數(shù)以字符串形式存儲(chǔ),對(duì)精度要求高時(shí)使用decimal較好;盡量避免對(duì)浮點(diǎn)數(shù)進(jìn)行減法和比較運(yùn)算。?
2.時(shí)間/日期類(lèi)型:?
year范圍:1901~2155;?
time格式:‘HH:MM:SS’(如果省略寫(xiě),并且沒(méi)有冒號(hào),則默認(rèn)最右起2位為秒,再到分,最后到時(shí));?
插入系統(tǒng)當(dāng)前時(shí)間:insert into 表名 values(current_date()),(now());?
date類(lèi)型:‘YYYY-MM-DD’;?
datetime(日期+時(shí)間):‘YYYY-MM-DD HH:MM:SS’或‘YYYYMMDDHHMMSS’,取值范圍:‘1000-01-01 00:00:00’~‘9999-12-31 23:59:59’;?
timestamp格式同datetime,但在存儲(chǔ)時(shí)需要4個(gè)字節(jié)(datetime需要8字節(jié)),并且以UTC(世界標(biāo)準(zhǔn)時(shí)間)進(jìn)行存儲(chǔ)(即timestamp會(huì)隨設(shè)置的時(shí)區(qū)而變化,而datetime存儲(chǔ)的絕不會(huì)變化);timestamp的范圍:1970-2037。?
3.字符串類(lèi)型:?
text類(lèi)型:tinytext、text、mediumtext、longtext;
類(lèi)型
范圍
tinytext ? ?255=2^8-1 ?
text ? ?65535=2^16-1 ?
mediumtext ? ?16777215=2^24-1 ?
longtext ? ?4294967295=4GB=2^32-1 ?
char的存儲(chǔ)需求是定義時(shí)指定的固定長(zhǎng)度;varchar的存儲(chǔ)需求是取決于實(shí)際值長(zhǎng)度。?
set類(lèi)型格式:set(’值1’,’值2’…) ——可以有0或者多個(gè)值,對(duì)于set而言,若插入的值為重復(fù)的,則只娶一個(gè)。插入的值亂序,則自動(dòng)按順序插入排列。插入不正常值,則忽略。?
二進(jìn)制類(lèi)型:?
bit(M)——保存位字段值(位字段類(lèi)型),M表示值的位數(shù);?
eg:select BIN(b+0) from 表名;—–b為列名;b+0表示將二進(jìn)制的結(jié)果轉(zhuǎn)換為對(duì)應(yīng)的數(shù)字的值,BIN()函數(shù)將數(shù)字轉(zhuǎn)換為二進(jìn)制。?
blog——-二進(jìn)制大對(duì)象,用來(lái)存儲(chǔ)可變數(shù)量的數(shù)據(jù)。
數(shù)據(jù)類(lèi)型
存儲(chǔ)范圍(字節(jié))
tinyblog ? ?最多255=2^8-1 字節(jié) ?
bolg ? ?最多65535=2^16-1 字節(jié) ?
mediumblog ? ?最多16777215=2^24-1 字節(jié) ?
longblog ? ?最多4294967295=4GB=2^32-1 字節(jié) ?