mysql如何高效存储IPv4、IPv6地址
目錄
- 一、IPv4簡介 + 高效存儲
- 二、 IPv6簡介 + 高效存儲(兼容IPv4)
- 三、引用:
一、IPv4簡介 + 高效存儲
IPv4百度百科,簡單地來說IPv4地址是一個4字節(jié)的無符號整數(shù)。為了方便人類閱讀和分析,IPv4通常被寫作點分十進制的形式,即四個字節(jié)被分開用十進制寫出,中間用點分隔。所以如何存儲IPv4,在腦海中想到的第一個答案是用varchar也是很自然的事情。但是使用varchar要使用的字節(jié)數(shù)是3*4+3+1 = 16,其中1指的是varchar需要一個字節(jié)保存長度(varchar的長度小于等于255時,需要一個字節(jié)保存長度)。使用int是4個字節(jié),使用varcahr是16個字節(jié)。在《高性能MySQL 第三版》中,關(guān)于字段的設(shè)計原則有:在夠用的前提下,字節(jié)能省則省。所以用無符號的int存儲IPv4是最好的選擇。
如何使用int類型存取IPv4?
登錄日志表 login_log(MySQL5.6+):
插入一條記錄:
INSERT INTO login_log(user_id, times, ipv4, ipv4_string) VALUES(1, 1 ,INET_ATON("192.168.1.5"), "192.168.1.5");查詢記錄:
SELECT *, INET_NTOA(ipv4) FROM login_log ; +----+---------+-------+----------------------------+----------------------------+------------+-------------+------+-----------------+ | id | user_id | times | login_time | update_time | ipv4 | ipv4_string | ip | INET_NTOA(ipv4) | +----+---------+-------+----------------------------+----------------------------+------------+-------------+------+-----------------+ | 1 | 1 | 1 | 0000-00-00 00:00:00.000000 | 0000-00-00 00:00:00.000000 | 3232235781 | 192.168.1.5 | NULL | 192.168.1.5 | +----+---------+-------+----------------------------+----------------------------+------------+-------------+------+-----------------+INET_ATON() 將IPv4的字符串地址轉(zhuǎn)換成數(shù)值,
INET_NTOA() 將IPv4的數(shù)值轉(zhuǎn)換成字符串地址。
二、 IPv6簡介 + 高效存儲(兼容IPv4)
至此,我們高效地存儲了IPv4。但是,不幸的是IPv4地址(約43億個)已經(jīng)用完了。所以,現(xiàn)在很多網(wǎng)址使用IPv6(百度百科)。簡單地來說,IPv6是一個16字節(jié)的整數(shù)。如何高效存儲IPv6這個16字節(jié)的整數(shù)?當然,我們可以套用上面存儲IPv4的思路,使用16字節(jié)的整數(shù)存儲IPv6。可惜的是,MySQL不支持16字節(jié)的整數(shù)(最大為8字節(jié)的bigint類型),所以無法使用整數(shù)存儲IPv6。那么,這時候varchar似乎又成了首選答案,但真的應(yīng)該使用varchar嗎?不妨讓我們先看看IPv6的三種常見的表示方式。
一、冒分十六進制表示法
格式為X:X:X:X:X:X:X:X,其中每個X表示地址中的16b,以十六進制表示,例如:ABCD:EF01:2345:6789:ABCD:EF01:2345:6789這種表示法中,每個X的前導(dǎo)0是可以省略的,例如:
2001:0DB8:0000:0023:0008:0800:200C:417A→2001:DB8:0:23:8:800:200C:417A
二、0位壓縮表示法
在某些情況下,一個IPv6地址中間可能包含很長的一段0,可以把連續(xù)的一段0壓縮為“::”。但為保證地址解析的唯一性,地址中”::”只能出現(xiàn)一次,例如:FF01:0:0:0:0:0:0:1101 → FF01::1101,0:0:0:0:0:0:0:1 → ::1,0:0:0:0:0:0:0:0 → ::
三、內(nèi)嵌IPv4地址表示法
為了實現(xiàn)IPv4-IPv6互通,IPv4地址會嵌入IPv6地址中,此時地址常表示為:X:X:X:X:X:X:d.d.d.d,前96b采用冒分十六進制表示,而最后32b地址則使用IPv4的點分十進制表示,例如::192.168.0.1與::FFFF:192.168.0.1就是兩個典型的例子,注意在前96b中,壓縮0位的方法依舊適用。
如果使用varchar類型保存IPv6的話,那么在存儲以冒分十六進制表示的IPv6時,就需要39 + 1 = 40 個字節(jié)。可IPv6本質(zhì)上一個16字節(jié)的數(shù)字,難道真的沒有其它辦法了嗎?在《高性能MySQL 第三版》中有句話“與CHAR和VARCHAR類似的類型還有BINARY和VARBINARY,它們存儲的是二進制字符串。二進制字符串和常規(guī)字符串非常相似,但是二進制字符串存儲的是字節(jié)碼而不是字符。”同時,要注意到VARBINARY(m),其中m表示字節(jié)數(shù)。這樣我們可以使用VARBINARY(16)存儲IPv6地址,并且兼容存儲IPv4地址。
插入用三種不同方式表示IPv6地址的記錄:
查詢記錄:
SELECT *, INET6_NTOA(ip) FROM login_log ;
INET6_ATON() 將IPv6的字符串地址轉(zhuǎn)換成數(shù)值(MySQL5.6+),
INET6_NTOA() 將IPv6的數(shù)值轉(zhuǎn)換成字符串地址(MySQL5.6+)。
三、引用:
- MySQL官網(wǎng)
- StackOverflow
- IPv6百度百科
- 《高性能MySQL 第三版》
總結(jié)
以上是生活随笔為你收集整理的mysql如何高效存储IPv4、IPv6地址的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我要做-微处理器嵌入式系统设计师
- 下一篇: 实时计算 Flink SQL 核心功能解