面試官:數(shù)據(jù)庫(kù)怎樣保存 IP 地址?
數(shù)據(jù)庫(kù)保存 IP 地址是偶爾會(huì)遇到的存儲(chǔ)場(chǎng)景,今天來(lái)聊一聊數(shù)據(jù)庫(kù)怎樣保存 IP 地址。
PostgreSQL
PostgreSQL 使用 INET 類型存儲(chǔ) IP 地址,IPv4 或 IPv6 都可以存儲(chǔ),同時(shí)也可以存儲(chǔ)子網(wǎng)信息。
存儲(chǔ)格式為 IP/子網(wǎng)掩碼位數(shù),比如:192.168.1.1/24。插入 SQL 如下:
INSERT INTO ip_test(id, ip) VALUES (1, '192.168.1.1/24');INET 類型可以對(duì) IP 地址進(jìn)行輸入校驗(yàn)、子網(wǎng)包含判斷等操作,提升數(shù)據(jù)完整性和查詢效率。比如下面語(yǔ)句判斷子網(wǎng)是否包含,結(jié)果返回 true:
SELECT '192.168.1.5'::inet << '192.168.1.0/24'::inet;MySQL
MySQL 可以使用 VARCHAR 類型保存 IP 地址,但是并不推薦,因?yàn)?nbsp;MySQL 提供了專門的保存 IP 地址的數(shù)據(jù)類型。
IPV4
MySQL 推薦使用 INT UNSIGNED 類型保存 IPV4 地址,并且提供了專門的函數(shù) INET_ATON(將 IP 轉(zhuǎn)為整數(shù))和 INET_NTOA(將整數(shù)轉(zhuǎn)為 IP) 進(jìn)行轉(zhuǎn)換。首先我們創(chuàng)建一張表:
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 是插入和查詢的實(shí)例:
--插入
INSERT INTO ip_test VALUES(1,INET_ATON('192.168.1.5'));
--查詢
SELECT  id, INET_NTOA(ip) FROM ip_test;使用 INT UNSIGNED 類型保存 IPV4 地址,有如下好處:
- 存儲(chǔ)空間更小,僅 4 個(gè)字節(jié);
 - 支持范圍查詢和索引優(yōu)化,查詢性能更好。
 
IPv6
對(duì)于 IPv6 類型地址,MySQL 可以使用 VARBINARY(16) 類型存儲(chǔ),并且提供了 INET6_ATON 和 INET6_NTOA 函數(shù)進(jìn)行轉(zhuǎn)換。我們?cè)賱?chuàng)建一張保存 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 是插入和查詢的實(shí)例:
--插入
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;總結(jié)
主流數(shù)據(jù)庫(kù)一般不推薦直接使用 VARCHAR 類型來(lái)存儲(chǔ) IP 地址,而是提供了內(nèi)置的類型和函數(shù),存儲(chǔ)和查詢效率更高。















 
 
 










 
 
 
 