mysql - 有没有办法直接从 SELECT 查询中将 IP 与 IP+CIDR​​ 匹配?

标签 mysql ip mask bitmask cidr

有点像

SELECT COUNT(*) AS c FROM BANS WHERE typeid=6 AND (SELECT ipaddr,cidr FROM BANS) MATCH AGAINST 'this_ip';

因此,您不必先从数据库中获取所有记录,然后逐条匹配它们。

如果 c > 0 那么匹配。

禁令表:

id int auto incr PK
typeid TINYINT (1=hostname, 4=ipv4, 6=ipv6)
ipaddr BINARY(128)
cidr INT
host VARCHAR(255)

数据库:MySQL 5

IP 和 IPv 类型(4 或 6)在查询时是已知的。

IP 例如二进制格式的::1

BANNED IP 例如:::1/64

最佳答案

请记住,IP 不是文本地址,而是数字 ID。我有类似的情况(我们正在做geo-ip查找),如果您将所有IP地址存储为整数(例如,我的IP地址是192.115.22.33所以它存储为3228767777),那么您可以查找IP使用右移运算符很容易。

所有这些类型的查找的缺点是您无法从索引中受益,并且每次查找时都必须进行全表扫描。上述方案可以通过存储CIDR网络的网络IP地址(范围的开始)和广播地址(范围的结束)来改进,例如存储192.168.1.0/24可以存储两个列:

network     broadcast
3232235776, 3232236031 

然后你就可以简单地匹配它

SELECT count(*) FROM bans WHERE 3232235876 >= network AND 3232235876 <= broadcast

这将使您可以将 CIDR 网络存储在数据库中,并利用快速数字索引将它们与 IP 地址快速有效地匹配。

以下讨论的注意事项:

MySQL 5.0 包含一个名为“index merge intersect”的范围查询优化,它允许加速此类查询(并避免全表扫描),只要:

  • 有一个多列索引按顺序与查询中的列完全匹配。所以 - 对于上面的查询示例,索引需要是 (network, broadcast)
  • 可以从索引中检索所有数据。这适用于 COUNT(*),但不适用于 SELECT * ... LIMIT 1

MySQL 5.6 包含一个称为 MRR 的优化,它也可以加快全行检索,但这超出了此答案的范围。

关于mysql - 有没有办法直接从 SELECT 查询中将 IP 与 IP+CIDR​​ 匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/595748/

相关文章:

ios - iOS 中 UIImageView 的动画圆形 mask

MySql如何获取每小时平均计数

linux - 在主机访问控制中配置后无法访问 WHM 和 SSH/root

c - 为什么在ping程序中内核没有去掉IP层

kubernetes - kubectl : Unable to connect to the server : dial tcp 192. 168.214.136:6443:连接:主机没有路由

actionscript-3 - Actionscript3 alpha 掩蔽?

php - WooCommerce 触发所有订单更新

php - 倒计时器与php mysql交互

php - 仅当两列(持续时间和分数)不同时,如何增加 mysql 中的排名?

css - 反转/更改 SVG 中嵌入 SVG 的填充颜色