3

在 MySQL 数据库中存储多种 IP 类型的最佳方法是什么,例如:
- 单个 IP (123.123.123.123)
- IP 范围 (123.123.123.1 - 123.123.123.121)
- IP 块 (123.123.123.1/20)
- IP 类别 ( 123.123.123.* 或 123.123 .. )

我正在考虑将所有范围/块/类转换为单个 IP 并使用 ip2long 存储它们以便更快地搜索到表中,但这将导致一个超过 100 万个数据库,我也需要不时减少/扩大类或更改/删除 IP 块。

每次有人访问我的网站时都会访问此数据库(因此需要快速)。有任何想法吗?

4

3 回答 3

3

本教程可以提供帮助:http ://daipratt.co.uk/mysql-store-ip-address/

保存 IPv4 地址的最有效方法是使用 INT 字段(不是您可能期望的 VARCHAR)。您可以使用 PHP 的 ip2long 转换它们,然后使用 MySQL 的 INET_NTOA 函数或 PHP 的 longtoip 转换它们。

来源:使用 PHP 将 IP 地址存储在 MySQL 数据库中

于 2013-10-22T22:26:15.300 回答
2

就像是:

CREATE TABLE ip_ranges (
  id         INT UNSIGNED AUTO_INCREMENT,
  ip_start   INT UNSIGNED NOT NULL,
  ip_end     INT UNSIGNED DEFAULT NULL,
  ip_subnet  TINYINT UNSIGNED DEFAULT NULL,
  ip_class   ENUM('A', 'B', 'C') DEFAULT NULL
)

哪里ip_start是必需的,所有其他字段可以是 NULL [单一 IP 规则] 或者可以设置另一个:

  • ip_end是范围 [192.168.1.10 到 192.168.1.15] 规范的结束部分
  • ip_subnet是子网掩码 [192.168.1.0/22]
  • ip_class是网络类,尽管这些在逻辑上可以存储为 /8、/16 或 /24 子网。

完全无视ip_class...

SELECT *
FROM ip_ranges
WHERE
  $ipaddr BETWEEN ip_start AND ip_end
  OR
  $ipaddr BETWEEN
    (ip_start &~ (POW(2,32-ip_subnet)-1)) AND
    (ip_start |  (POW(2,32-ip_subnet)-1))

应该选择任何适用于$ipaddr. [但我没有测试过]

于 2013-10-22T23:38:48.650 回答
0

您可以将所有类型的地址存储为 LineString(Point(-1, first_ip_iplong), Point(+1, last_ip_iplong)),为该字段添加索引并享受几乎任何数据或记录计数的即时搜索(使用 MBRIntersects )。

更多信息可以在这里找到

请注意,这种做法会在 mysql 中紧密耦合您的代码。

于 2013-10-22T22:30:30.927 回答