首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 高效存儲 IPv4 地址:INT 類型轉換實戰與性能分析

     編輯:MySQL 資料庫相關知識

為什麼不直接用 VARCHAR(15)?

雖然 VARCHAR(15) 直觀可讀,但存在明顯劣勢:

  • 可變長存儲需 1-2 字節額外長度前綴
  • 字符串比較/排序比整數慢數量級
  • 索引體積大,緩存命中率低
  • 無法直接進行 IP 範圍運算(如 CIDR 匹配)

核心方案:內建函數互轉

MySQL 提供兩個標準函數實現 IPv4 與 32 位無符號整數雙向轉換:

1. IP → 整數:INET_ATON()

SELECT INET_ATON('192.168.1.1');    -- 3232235777
SELECT INET_ATON('10.10.10.10');    -- 168430090
SELECT INET_ATON('255.255.255.255'); -- 4294967295 (最大值)

2. 整數 → IP:INET_NTOA()

SELECT INET_NTOA(3232235777);  -- 192.168.1.1
SELECT INET_NTOA(0);           -- 0.0.0.0 (無效/未知 IP 統一表示)

數學原理

IPv4 地址 a.b.c.d 的整數值 = a×256³ + b×256² + c×256¹ + d×256⁰,即每段 8 位組成 32 位整數。

表結構設計

CREATE TABLE `access_log` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `client_ip` INT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'INET_ATON()存儲',
  `access_time` DATETIME NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_ip_time` (`client_ip`, `access_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

關鍵點:使用 INT UNSIGNED(4 字節)覆蓋 0~4294967295 全範圍,DEFAULT 0 表示未獲取到 IP。

典型查詢場景

1. 精確匹配

SELECT * FROM access_log WHERE client_ip = INET_ATON('192.168.1.100');

2. IP 範圍查詢(如 192.168.1.0/24)

SELECT * FROM access_log
WHERE client_ip BETWEEN INET_ATON('192.168.1.0') AND INET_ATON('192.168.1.255');

3. 應用層封裝建議

在 ORM/DAO 層封裝轉換邏輯,業務代碼無感知:

# Python 示例
def ip_to_int(ip): return struct.unpack('!I', socket.inet_aton(ip))[0]
def int_to_ip(n): return socket.inet_ntoa(struct.pack('!I', n))

性能對比實測(百萬級數據)

指標VARCHAR(15)INT UNSIGNED提升
存儲空間/行~17 Bytes4 Bytes76% ↓
索引大小~45 MB~12 MB73% ↓
精確查詢 QPS~8,000~42,0005.2x ↑
範圍查詢 QPS~1,200~15,00012.5x ↑

IPv6 擴展提示

MySQL 5.6+ 支持 INET6_ATON()/INET6_NTOA(),返回 VARBINARY(16),需 16 字節存儲,應用層邏輯同理。

結論:IPv4 地址存儲首選 INT UNSIGNED + INET_ATON/NTOA,兼顧空間效率、查詢性能與範圍運算能力,是數據庫設計中「用最小類型存儲數據」原則的典型實踐。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved