來(lái)源:飛天小牛肉
提到 IP 地址(IPv4),大伙兒腦子里肯定馬上能浮現(xiàn)類(lèi)似于 192.168.0.1、127.0.0.1 這種常見(jiàn)的 IP 地址,然后結(jié)合這個(gè)問(wèn)題 “MySQL 中用什么數(shù)據(jù)類(lèi)型存 IP 地址?”,于是乎脫口而出用 char 字符串類(lèi)型存。
面試官一臉冷漠,你頓時(shí)意識(shí)到情況不對(duì),又仔細(xì)琢磨了一下。
然后發(fā)現(xiàn),這個(gè) IP 地址的長(zhǎng)度是變化的,最短可以是 0.0.0.0 只需要 7 位,最長(zhǎng)可以是 255.255.255.255 需要 15 位,于是自信地回答使用 varchar(15) 來(lái)存儲(chǔ) IP 地址,并為自己能夠想到這一層而暗自竊喜。
誰(shuí)知面試官竟輕蔑一笑,問(wèn)你 “確定嗎?”,你覺(jué)得這是面試官在考驗(yàn)?zāi)?,于是?jiān)定的回答 “確定”。
然后就開(kāi)始了下一題
......
人們經(jīng)常使用 varchar(15) 列來(lái)存儲(chǔ) IP 地址,但事實(shí)上這并不是最優(yōu)解。
IP 地址的本質(zhì)是 32 位無(wú)符號(hào)整數(shù),類(lèi)似于 192.168.0.1 這種點(diǎn)分十進(jìn)制的字符串寫(xiě)法只是為了幫助人們理解和記憶,192.168.0.1 對(duì)應(yīng)的十進(jìn)制表示是 無(wú)符號(hào)整數(shù) 3232235521。
所以,說(shuō)用字符串類(lèi)型存 IP 地址的,其實(shí)是潛意識(shí)中以為 IP 地址是字符串,存的是點(diǎn)分十進(jìn)制的字符串,但正確的應(yīng)該是存 32 位的無(wú)符號(hào)整數(shù)
所謂有符號(hào)數(shù)其實(shí)就是將最高位作為符號(hào)位,比如 32 位的有符號(hào) INT,最高位是符號(hào)位,剩下 31 位才是真實(shí)的數(shù)值,所以有符號(hào) INT 的取值區(qū)間為:
無(wú)符號(hào) INT 的取值區(qū)間為:
下表列出了 MySQL 出各個(gè)整數(shù)類(lèi)型有符號(hào)和無(wú)符號(hào)的的取值范圍,在定義表時(shí),可以在數(shù)據(jù)類(lèi)型后面添加關(guān)鍵字 UNSIGNED 來(lái)定義無(wú)符號(hào)整數(shù),否則默認(rèn)為有符號(hào)整數(shù):
| 類(lèi)型 | 有符號(hào)數(shù)取值范圍 | 無(wú)符號(hào)數(shù)取值范圍 |
|---|---|---|
| TINYINT(1 字節(jié),8 bit) | -128 ? 127 | 0 ? 255 |
| SMALLINT(2 字節(jié),16 bit) | -32768 ? 32767 | 0 ? 65535 |
| MEDIUMINT(3 字節(jié),24 bit) | -8388608 ? 8388607 | 0 ? 16777215 |
| INT(4 字節(jié),32 bit) | -2147483648 ? 2147483647 | 0 ? 4294967295 |
| BIGINT(8 字節(jié),64 bit) | -9223372036854775808 ? 9223372036854775807 | 0 ? 18446744073709551615 |
結(jié)合上表,可以看出,32 位的無(wú)符號(hào) INT 正好可以容納 IPv4 地址,下面是 INT UNSIGNED 和 VARCHAR(15) 兩種數(shù)據(jù)類(lèi)型的對(duì)比:
存儲(chǔ)空間:4 字節(jié)的 INT 類(lèi)型 15 字節(jié)的 VARCHAR(15) 更加節(jié)省存儲(chǔ)空間。另外,VARCHAR 除了會(huì)保存需要的字符數(shù),還會(huì)另加一個(gè)字節(jié)來(lái)記錄長(zhǎng)度(如果列聲明的長(zhǎng)度超過(guò) 255,則使用兩個(gè)字節(jié)記錄長(zhǎng)度),所以 VARCHAR(15) 其實(shí)要占用 16 個(gè)字節(jié)。
檢索速度:如果我們要在 IP 地址上建立索引,那么對(duì)于字符串索引來(lái)說(shuō),整數(shù)索引的檢索速度簡(jiǎn)直就是降緯打擊了,因?yàn)樽址?lèi)型的比較是需要從第一位字符開(kāi)始遍歷依次進(jìn)行的,速度較慢。
MySQL 非常貼心地提供了 IPv4 地址點(diǎn)分十進(jìn)制和無(wú)符號(hào)整數(shù)的相互轉(zhuǎn)換函數(shù),inet_aton 和 inet_ntoa(底層是二進(jìn)制移位操作,速度很快):

當(dāng)然你更應(yīng)該在業(yè)務(wù)中去執(zhí)行這些轉(zhuǎn)換,減輕 MySQL 的壓力。
審核編輯:湯梓紅
-
ip地址
+關(guān)注
關(guān)注
0文章
309瀏覽量
18939 -
IPv4
+關(guān)注
關(guān)注
0文章
145瀏覽量
20885 -
數(shù)據(jù)類(lèi)型
+關(guān)注
關(guān)注
0文章
237瀏覽量
14185 -
mysql架構(gòu)
+關(guān)注
關(guān)注
0文章
2瀏覽量
769
原文標(biāo)題:我懵了,如果要存 IP 地址,用什么數(shù)據(jù)類(lèi)型比較好?
文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
變量的數(shù)據(jù)類(lèi)型與類(lèi)型輸入連線的數(shù)據(jù)類(lèi)型不兼容。
照著別人的程序做了一遍,變量的數(shù)據(jù)類(lèi)型和輸入類(lèi)型不符
mysql是根據(jù)哪些原則來(lái)進(jìn)行數(shù)據(jù)類(lèi)型選擇的?
vhdl數(shù)據(jù)類(lèi)型
MySQL支持的三種數(shù)據(jù)類(lèi)型
MySQL為字段選擇合適數(shù)據(jù)類(lèi)型
MySQL中用什么數(shù)據(jù)類(lèi)型存IP地址
評(píng)論