淺談MySQL中用什么數(shù)據(jù)類型存IP地址
提到IP地址(IPv4),我們腦子里肯定立馬浮現(xiàn)類似于192.168.0.1、127.0.0.1這種常見的IP地址,然后結(jié)合這個(gè)問題“MySQL中用什么數(shù)據(jù)類型存IP地址?”,于是乎脫口而出用char字符串類型存儲。
然后再仔細(xì)想想發(fā)現(xiàn),這個(gè)IP地址的長度是變化的,最短可以是0.0.0.0只需要 7 位,最長可以是255.255.255.255需要15位,于是自信地回答使用varchar(15)來存儲 IP 地址,并為自己能夠想到這一層而暗自竊喜。
人們經(jīng)常使用varchar(15)列來存儲 IP 地址,但事實(shí)上這并不是最優(yōu)解。
IP地址的本質(zhì)是32位無符號整數(shù),類似于192.168.0.1這種點(diǎn)分十進(jìn)制的字符串寫法只是為了幫助人們理解和記憶,192.168.0.1對應(yīng)的十進(jìn)制表示是無符號整數(shù)3232235521。
所以說用字符串類型存IP 地址的,其實(shí)是潛意識中以為IP地址是字符串。實(shí)際存的是點(diǎn)分十進(jìn)制的字符串,但正確的應(yīng)該是存32位的無符號整數(shù)。
所謂有符號數(shù)其實(shí)就是將最高位作為符號位,比如32位的有符號int類型,最高位是符號位,剩下 31位才是真實(shí)的數(shù)值,所以有符號int類型的取值區(qū)間為:
[-2^31,2^3-1]
無符號int類型的取值區(qū)間為:
[0,2^32]
下表列出了MySQL中各個(gè)整數(shù)類型有符號和無符號的的取值范圍,在定義表時(shí),可以在數(shù)據(jù)類型后面添加關(guān)鍵字 UNSIGNED 來定義無符號整數(shù),否則默認(rèn)為有符號整數(shù):
特別說明:ASCII碼中,1個(gè)漢字字符存儲需要2個(gè)字節(jié),1個(gè)英文字符存儲需要1個(gè)字節(jié)。
結(jié)合上表,可以看出32位的無符號 int類型正好可以容納 IPv4 地址,下面是 INT UNSIGNED 和 VARCHAR(15) 兩種數(shù)據(jù)類型的對比:
- 存儲空間: 4 字節(jié)的int類型比15字節(jié)的varchar(15)更加節(jié)省存儲空間。另外varchar除了會保存需要的字符,還會另加一個(gè)字節(jié)來記錄長度(如果列聲明的長度超過255,則使用兩個(gè)字節(jié)記錄長度),所以varchar(15)其實(shí)要占用 16 個(gè)字節(jié)。
檢索速度:如果我們要在 IP 地址上建立索引,那么對于字符串索引來說,整數(shù)索引的檢索速度簡直就是降緯打擊了,因?yàn)樽址愋偷谋容^是需要從第一位字符開始遍歷依次進(jìn)行的,速度較慢。
MySQL非常貼心地提供了IPv4地址點(diǎn)分十進(jìn)制和無符號整數(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ù)類型存IP地址的文章就介紹到這了,更多相關(guān)MySQL存IP地址內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL:explain結(jié)果中Extra:Impossible?WHERE?noticed?after?rea
這篇文章主要介紹了MySQL:explain結(jié)果中Extra:Impossible?WHERE?noticed?after?reading?const?tables問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12phpMyAdmin下將Excel中的數(shù)據(jù)導(dǎo)入MySql的圖文方法
使用phpMyAdmin將Excel中的數(shù)據(jù)導(dǎo)入MySql,需要將execl導(dǎo)入到mysql數(shù)據(jù)庫的朋友可以參考下。2010-08-08詳解MySql基本查詢、連接查詢、子查詢、正則表達(dá)查詢
本篇文章采用了圖文相結(jié)合的方式介紹了數(shù)據(jù)庫的四大查詢方式:基本查詢、連接查詢、子查詢、正則表達(dá)查詢,需要了解的朋友可以參考下2015-07-07mysql啟動的error 2003和1067錯(cuò)誤問題解決方法
mysql安裝好經(jīng)常發(fā)現(xiàn)無法正常啟動碰到最多的是error 2003的錯(cuò)誤,經(jīng)研究在此附上解決方法,希望可以幫助有類似問題的朋友2013-09-09mysql數(shù)據(jù)庫實(shí)現(xiàn)設(shè)置字段長度
這篇文章主要介紹了mysql數(shù)據(jù)庫實(shí)現(xiàn)設(shè)置字段長度,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06phpmyadmin報(bào)錯(cuò):#2003 無法登錄 MySQL服務(wù)器的解決方法
通過phpmyadmin連接mysql數(shù)據(jù)庫時(shí)提示:“2003 無法登錄 MySQL服務(wù)器”。。。很明顯這是沒有啟動mysql服務(wù),右擊我的電腦-管理-找到服務(wù),找到mysql啟動一下2012-04-04MySQL中DATEDIFF()函數(shù)用法及返回周、月、年
這篇文章主要給大家介紹了關(guān)于MySQL中DATEDIFF()函數(shù)用法及返回周、月、年的相關(guān)資料,datediff()函數(shù)返回兩個(gè)日期之間的時(shí)間,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11Mysql查看數(shù)據(jù)庫時(shí)區(qū)并設(shè)置時(shí)區(qū)的方法
這篇文章主要介紹了Mysql查看數(shù)據(jù)庫時(shí)區(qū)并設(shè)置時(shí)區(qū)的方法,設(shè)置時(shí)區(qū)的方式可以通過mysql命令行模式下動態(tài)修改以及通過修改配置文件來修改時(shí)區(qū),需要的朋友可以參考下2024-02-02