存ip地址,用什么數(shù)據(jù)類型比較好
存ip地址時(shí),相對(duì)字符串存儲(chǔ),使用無符號(hào)整數(shù)來存儲(chǔ)有如下的好處:
- 節(jié)省空間,不管是數(shù)據(jù)存儲(chǔ)空間,還是索引存儲(chǔ)空間
- 便于使用范圍查詢(BETWEEN...AND),且效率更高
VARCHAR(15)
即可。MySQL在保存變長的字符串時(shí),還需要額外的一個(gè)字節(jié)來保存此字符串的長度。而如果使用無符號(hào)整數(shù)來存儲(chǔ),只需要4個(gè)字節(jié)即可。另外還可以使用4個(gè)字段分別存儲(chǔ)IPv4中的各部分,但是通常這不管是存儲(chǔ)空間和查詢效率應(yīng)該都不是很高(可能有的場景適合使用這種方式存儲(chǔ))。使用字符串和無符號(hào)整數(shù)來存儲(chǔ)IP的具體性能分析及benchmark,可以看這篇文章。https://bafford.com/2009/03/09/mysql-performance-benefits-of-storing-integer-ip-addresses/使用無符號(hào)整數(shù)來存儲(chǔ)也有缺點(diǎn):
- 不便于閱讀
- 需要手動(dòng)轉(zhuǎn)換
INET_ATON
,以及把整數(shù)格式的IP轉(zhuǎn)換成字符串的INET_NTOA
。如下所示:mysql>?select?inet_aton('192.168.0.1');
--------------------------
|?inet_aton('192.168.0.1')?|
--------------------------
|???????????????3232235521?|
--------------------------
1?row?in?set?(0.00?sec)
mysql>?select?inet_ntoa(3232235521);
-----------------------
|?inet_ntoa(3232235521)?|
-----------------------
|?192.168.0.1???????????|
-----------------------
1?row?in?set?(0.00?sec)
對(duì)于IPv6來說,使用VARBINARY
同樣可獲得相同的好處,同時(shí)MySQL也提供了相應(yīng)的轉(zhuǎn)換函數(shù),即INET6_ATON
和INET6_NTOA
。對(duì)于轉(zhuǎn)換字符串IPv4和數(shù)值類型,可以放在應(yīng)用層,下面是使用java代碼來對(duì)二者轉(zhuǎn)換:package?com.mikan;
/**
?*?@author?Mikan
?*/
public?class?IpLongUtils?{
????/**
?????*?把字符串IP轉(zhuǎn)換成long
?????*
?????*?@param?ipStr?字符串IP
?????*?@return?IP對(duì)應(yīng)的long值
?????*/
????public?static?long?ip2Long(String?ipStr)?{
????????String[]?ip?=?ipStr.split("\\.");
????????return?(Long.valueOf(ip[0])?<24)? ?(Long.valueOf(ip[1])?<16)
???????????????? ?(Long.valueOf(ip[2])?<8)? ?Long.valueOf(ip[3]);
????}
????/**
?????*?把IP的long值轉(zhuǎn)換成字符串
?????*
?????*?@param?ipLong?IP的long值
?????*?@return?long值對(duì)應(yīng)的字符串
?????*/
????public?static?String?long2Ip(long?ipLong)?{
????????StringBuilder?ip?=?new?StringBuilder();
????????ip.append(ipLong?>>>?24).append(".");
????????ip.append((ipLong?>>>?16)?