当前位置:  开发笔记 > 后端 > 正文

有没有办法直接从SELECT查询匹配IP与IP + CIDR?

如何解决《有没有办法直接从SELECT查询匹配IP与IP+CIDR?》经验,为你挑选了1个好方法。

就像是

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

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

如果c> 0则匹配.

BANS表:

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

DB:MySQL 5

查询时已知IP和IPv6类型(4或6).

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

BANNED IP例如是:: 1/64



1> Guss..:

请记住,IP不是文本地址,而是数字ID.我有类似的情况(我们正在进行地理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包括称为" 索引合并交叉 " 的远程查询优化,它允许加速此类查询(并避免全表扫描),只要:

有一个多列索引,它按顺序与查询中的列完全匹配.所以 - 对于上面的查询示例,索引需要(network, broadcast).

可以从索引中检索所有数据.这是真的COUNT(*),但事实并非如此SELECT * ... LIMIT 1.

MySQL 5.6包含一个称为MRR的优化,它也可以加速完整行检索,但这超出了这个答案的范围.

推荐阅读
刘美娥94662
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有