淺談MySQL中用什么數(shù)據(jù)類(lèi)型存IP地址
提到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)型存儲(chǔ)。
然后再仔細(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 地址,并為自己能夠想到這一層而暗自竊喜。
人們經(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地址是字符串。實(shí)際存的是點(diǎn)分十進(jìn)制的字符串,但正確的應(yīng)該是存32位的無(wú)符號(hào)整數(shù)。
所謂有符號(hào)數(shù)其實(shí)就是將最高位作為符號(hào)位,比如32位的有符號(hào)int類(lèi)型,最高位是符號(hào)位,剩下 31位才是真實(shí)的數(shù)值,所以有符號(hào)int類(lèi)型的取值區(qū)間為:
[-2^31,2^3-1]
無(wú)符號(hào)int類(lèi)型的取值區(qū)間為:
[0,2^32]
下表列出了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ù):

特別說(shuō)明:ASCII碼中,1個(gè)漢字字符存儲(chǔ)需要2個(gè)字節(jié),1個(gè)英文字符存儲(chǔ)需要1個(gè)字節(jié)。
結(jié)合上表,可以看出32位的無(wú)符號(hào) int類(lèi)型正好可以容納 IPv4 地址,下面是 INT UNSIGNED 和 VARCHAR(15) 兩種數(shù)據(jù)類(lèi)型的對(duì)比:
- 存儲(chǔ)空間: 4 字節(jié)的int類(lèi)型比15字節(jié)的varchar(15)更加節(jié)省存儲(chǔ)空間。另外varchar除了會(huì)保存需要的字符,還會(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)制移位操作,速度很快)。
點(diǎn)分十進(jìn)制 -> 十進(jìn)制:
SELECT INET_ATON('192.168.0.1');
十進(jìn)制 -> 點(diǎn)分十進(jìn)制:
SELECT INET_NTOA('3232235521');
當(dāng)然我們更應(yīng)該在業(yè)務(wù)中去執(zhí)行這些轉(zhuǎn)換,減輕 MySQL 的壓力:
public class Demo {
public static void main(String[] args) {
String ipStr = "192.168.0.1";
long ip =ip2int(ipStr);
System.out.println(ip);
}
public static long ip2int(String ip) {
String[] items = ip.split("\\.");
return Long.valueOf(items[0]) << 24 | Long.valueOf(items[1]) << 16 | Long.valueOf(items[2]) << 8 | Long.valueOf(items[3]);
}
public static String int2ip(long ipInt) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append((ipInt >> 24) & 0xFF).append(".");
stringBuilder.append((ipInt >> 16) & 0xFF).append(".");
stringBuilder.append((ipInt >> 8) & 0xFF).append(".");
stringBuilder.append(ipInt & 0xFF);
return stringBuilder.toString();
}
}到此這篇關(guān)于淺談MySQL中用什么數(shù)據(jù)類(lèi)型存IP地址的文章就介紹到這了,更多相關(guān)MySQL存IP地址內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mysql inner join on的用法實(shí)例(必看)
下面小編就為大家?guī)?lái)一篇Mysql inner join on的用法實(shí)例(必看)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03
mysql雙機(jī)熱備實(shí)現(xiàn)方案【可測(cè)試】
雙機(jī)熱備從廣義上講,就是對(duì)于重要的服務(wù),使用兩臺(tái)服務(wù)器,互相備份,共同執(zhí)行同一服務(wù)。這篇文章主要介紹了mysql雙機(jī)熱備實(shí)現(xiàn)方案,需要的朋友可以參考下2019-10-10
QT連接MYSQL數(shù)據(jù)庫(kù)的詳細(xì)步驟
這篇文章主要介紹了QT連接MYSQL數(shù)據(jù)庫(kù)的詳細(xì)步驟,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07
MySQL存儲(chǔ)過(guò)程的傳參和流程控制示例講解
這篇文章主要介紹了MySQL存儲(chǔ)過(guò)程的傳參和流程控制示例講解,?repeat和Loop區(qū)別是repeat有自己退出循環(huán)的語(yǔ)句until,Loop使用的是if判斷語(yǔ)句,本文結(jié)合示例代碼詳細(xì)講解,需要的朋友可以參考下2023-02-02
MySQL數(shù)據(jù)庫(kù)遠(yuǎn)程訪問(wèn)權(quán)限如何打開(kāi)(兩種方法)
本文通過(guò)兩種方法給大家介紹MySQL數(shù)據(jù)庫(kù)遠(yuǎn)程訪問(wèn)權(quán)限的打開(kāi)方法,非常不錯(cuò),實(shí)用性非常高,感興趣的朋友一起看看吧2016-05-05
Navicat導(dǎo)出MySQL數(shù)據(jù)庫(kù)表結(jié)構(gòu)到Excel過(guò)程
本文介紹了如何將數(shù)據(jù)庫(kù)中的表結(jié)構(gòu)導(dǎo)出到Excel文件中,包括使用SQL語(yǔ)句查詢(xún)表結(jié)構(gòu)并使用Navicat工具導(dǎo)出到Excel文件的步驟,總結(jié):將數(shù)據(jù)庫(kù)表結(jié)構(gòu)導(dǎo)出到Excel文件中,便于后續(xù)使用或存檔2026-01-01

