存储单个IP,IP范围,IP块和IP类的最佳方式,并快速搜索它们

时间:2013-10-22 22:24:02

标签: php mysql sql database ip

在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块。

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

3 个答案:

答案 0 :(得分:3)

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

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

来源:IP address storing in MySQL database using PHP

答案 1 :(得分: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的任何规则。 [但我还没有测试过]

答案 2 :(得分:-1)

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

可以找到更多信息here

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