MySQL存儲(chǔ)IP地址的方法
為什么要問如何存儲(chǔ)IP?
首先就來闡明一下部分人得反問:為什么要問IP得怎樣存,直接varchar類型不就得了嗎?
其實(shí)做任何程序設(shè)計(jì)都要在功能實(shí)現(xiàn)的基礎(chǔ)上最大限度的優(yōu)化性能。而數(shù)據(jù)庫設(shè)計(jì)是程序設(shè)計(jì)中不可忽略的一個(gè)重要部分,所以巧存IP地址可以一定程度獲得很大提升。
利用函數(shù)算法處理
在MySQL中沒有直接提供IP類型字段,但如果有兩個(gè)函數(shù)可以把IP與最大長度為10位數(shù)字類型互轉(zhuǎn),所以使用int類型存儲(chǔ)IP比varchar類型存儲(chǔ)IP地址性能要提升很多,減少不少空間。因?yàn)関archar是可變長形,需要多余的一個(gè)字節(jié)存儲(chǔ)長度。另外int型在邏輯運(yùn)算上要比varchar速度快。
IP轉(zhuǎn)數(shù)字函數(shù)inet_aton()
我們轉(zhuǎn)換下幾個(gè)常用的IP地址
mysql> select inet_aton('255.255.255.255'); +------------------------------+ | inet_aton('255.255.255.255') | +------------------------------+ | 4294967295 | +------------------------------+ 1 row in set (0.00 sec) mysql> select inet_aton('192.168.1.1'); +--------------------------+ | inet_aton('192.168.1.1') | +--------------------------+ | 3232235777 | +--------------------------+ 1 row in set (0.00 sec) mysql> select inet_aton('10.10.10.10'); +--------------------------+ | inet_aton('10.10.10.10') | +--------------------------+ | 168430090 | +--------------------------+ 1 row in set (0.00 sec)
所以IP的表字段可以設(shè)置為INT(10)就好,如果IP獲取不到可以直接存0代表獲取不到IP的意思
數(shù)字轉(zhuǎn)IP函數(shù)inet_ntoa()
mysql> select inet_ntoa(4294967295); +-----------------------+ | inet_ntoa(4294967295) | +-----------------------+ | 255.255.255.255 | +-----------------------+ 1 row in set (0.00 sec) mysql> select inet_ntoa(3232235777); +-----------------------+ | inet_ntoa(3232235777) | +-----------------------+ | 192.168.1.1 | +-----------------------+ 1 row in set (0.00 sec) mysql> select inet_ntoa(168430090); +----------------------+ | inet_ntoa(168430090) | +----------------------+ | 10.10.10.10 | +----------------------+ 1 row in set (0.00 sec) mysql> select inet_ntoa(0); +--------------+ | inet_ntoa(0) | +--------------+ | 0.0.0.0 | +--------------+ 1 row in set (0.00 sec)
注意,0轉(zhuǎn)換為 0.0.0.0
整型字段的比較比字符串效率高很多,這也符合一項(xiàng)優(yōu)化原則:字段類型定義使用最合適(最?。?,最簡單的數(shù)據(jù)類型。
inet_aton()算法,其實(shí)借用了國際上對(duì)各國IP地址的區(qū)分中使用的ip number。
a.b.c.d 的ip number是:
a * 256的3次方 + b * 256的2次方 + c * 256的1次方 + d * 256的0次方。
mysql 存儲(chǔ)ip地址
mysql提供了兩個(gè)方法來處理ip地址:
inet_aton 把ip轉(zhuǎn)為無符號(hào)整型(4-8位)
inet_ntoa 把整型的ip轉(zhuǎn)為電地址
插入數(shù)據(jù)前,先用inet_aton把ip地址轉(zhuǎn)為整型,可以節(jié)省空間。
顯示數(shù)據(jù)時(shí),使用inet_ntoa把整型的ip地址轉(zhuǎn)為電地址顯示即可。為社么這樣存?,性能上的提示比直接存儲(chǔ)字符串的IP要高出很多。
示例:
CREATE TABLE `t_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(15) DEFAULT NULL COMMENT '用戶名', `ip` bigint(20) DEFAULT NULL COMMENT 'IP地址', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
插入幾條數(shù)據(jù):
INSERT INTO `t_user` ( `id`, `name`, `ip` ) VALUES ( 2, 'babala', inet_aton( '127.0.0.1' ) ), ( 3, 'maly', inet_aton( '192.168.1.1' ) ), ( 4, 'kaven', inet_aton( '111.175.7.143' ) );
查詢顯示地址:
select id,name,inet_ntoa(ip) as ip from `t_user`;
如果需要找出在某個(gè)網(wǎng)段的用戶(例如:192.168.1.1 ~ 192.168.1.100),可以利用php的ip2long方法,把ip地址轉(zhuǎn)為整型,再進(jìn)行比較。
$ip_start = '192.168.1.1'; $ip_end = '192.168.1.100'; echo sprintf('%u',ip2long($ip_start)).PHP_EOL; // 3232235777 echo sprintf('%u',ip2long($ip_end)).PHP_EOL; // 3232235876
總結(jié)
1.保存ip地址到數(shù)據(jù)庫,使用unsigned int格式,插入時(shí)使用inet_aton方法把ip先轉(zhuǎn)為無符號(hào)整型,可以節(jié)省存儲(chǔ)空間。
2.顯示時(shí)使用inet_ntoa把整型ip地址轉(zhuǎn)為電地址。
3.php 使用 ip2long轉(zhuǎn)ip為整型時(shí),需要注意出現(xiàn)負(fù)數(shù)的問題(如果出現(xiàn)負(fù)數(shù):參照之前我寫的這篇)
以上講解的就是MySQL存儲(chǔ)IP地址的方法,希望能夠?qū)Υ蠹业膶W(xué)習(xí)有所幫助。
相關(guān)文章
MySQL數(shù)據(jù)庫實(shí)驗(yàn)之?觸發(fā)器和存儲(chǔ)過程
這篇文章主要介紹了MySQL數(shù)據(jù)庫實(shí)驗(yàn)之?觸發(fā)器和存儲(chǔ)過程,通過掌握某主流DBMS支持的SQL編程語言和編程規(guī)范,規(guī)范設(shè)計(jì)存儲(chǔ)過程展開詳細(xì)介紹,感興趣的朋友可以參考一下2022-06-06MySQL中ON DUPLICATE key update的使用
本文主要介紹了MySQL中ON DUPLICATE key update的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05

MySQL與PHP的基礎(chǔ)與應(yīng)用專題之創(chuàng)建數(shù)據(jù)庫表

mysql too many open connections問題解決方法

windows下安裝mysql8.0.18的教程(社區(qū)版)