面試官:數據庫怎樣保存 IP 地址?
數據庫保存 IP 地址是偶爾會遇到的存儲場景,今天來聊一聊數據庫怎樣保存 IP 地址。
PostgreSQL
PostgreSQL 使用 INET 類型存儲 IP 地址,IPv4 或 IPv6 都可以存儲,同時也可以存儲子網信息。
存儲格式為 IP/子網掩碼位數,比如:192.168.1.1/24。插入 SQL 如下:
INSERT INTO ip_test(id, ip) VALUES (1, '192.168.1.1/24');INET 類型可以對 IP 地址進行輸入校驗、子網包含判斷等操作,提升數據完整性和查詢效率。比如下面語句判斷子網是否包含,結果返回 true:
SELECT '192.168.1.5'::inet << '192.168.1.0/24'::inet;MySQL
MySQL 可以使用 VARCHAR 類型保存 IP 地址,但是并不推薦,因為 MySQL 提供了專門的保存 IP 地址的數據類型。
IPV4
MySQL 推薦使用 INT UNSIGNED 類型保存 IPV4 地址,并且提供了專門的函數 INET_ATON(將 IP 轉為整數)和 INET_NTOA(將整數轉為 IP) 進行轉換。首先我們創建一張表:
CREATE TABLE`ip_test` (
`id`bigint(20) NOTNULL AUTO_INCREMENT,
`ip`int(10) unsignedDEFAULTNULL,
KEY`id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2DEFAULTCHARSET=utf8 COLLATE=utf8_bin下面 SQL 是插入和查詢的實例:
--插入
INSERT INTO ip_test VALUES(1,INET_ATON('192.168.1.5'));
--查詢
SELECT id, INET_NTOA(ip) FROM ip_test;使用 INT UNSIGNED 類型保存 IPV4 地址,有如下好處:
- 存儲空間更小,僅 4 個字節;
- 支持范圍查詢和索引優化,查詢性能更好。
IPv6
對于 IPv6 類型地址,MySQL 可以使用 VARBINARY(16) 類型存儲,并且提供了 INET6_ATON 和 INET6_NTOA 函數進行轉換。我們再創建一張保存 IPV6 地址的表:
CREATE TABLE `ip_test_v6` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`ip` varbinary(16) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin下面 SQL 是插入和查詢的實例:
--插入
INSERT INTO ip_test_v6 (id,ip) VALUES (1, INET6_ATON('FC00:0:130F:0:0:9C0:876A:130B'));
--查詢
SELECT id, INET6_NTOA(ip) FROM ip_test_v6;總結
主流數據庫一般不推薦直接使用 VARCHAR 類型來存儲 IP 地址,而是提供了內置的類型和函數,存儲和查詢效率更高。




























