【问题标题】:Searching IP Ranges Efficiently PHP and MySQL高效搜索 IP 范围 PHP 和 MySQL
【发布时间】:2016-10-13 17:02:36
【问题描述】:

我有一个数据库,其中包含大约 100,000 个 IP 范围条目,我的网站将拒绝来自这些范围的请求。

存储这些范围的表格格式为

ip_from (int)
ip_to (int)

使用 PHP 我使用 ip2long 将用户 IP 转换为整数值

然后我使用以下 SQL 查询来确定用户 IP 是否存在于表中的某个范围内。

SELECT `ip_from` 
FROM `ip2location_proxy`
WHERE '".$ip."' BETWEEN ip_from AND ip_to LIMIT 1

问题是这会造成很大的服务器负载。我想知道是否有人可以建议一种更好的方法来检测 IP 是否在数据库中指定的范围内,例如使用 BETWEEN 命令的替代方法。

【问题讨论】:

  • 天哪,你为什么要禁止 10 万个 IP 地址?我不确定是否真的有一种方法可以有效地搜索每个 HTTP 请求的 10 万条记录。
  • 确保您在ip_fromip_to 上都有索引(我不认为将它们都编入索引会更好)。
  • 如果您使用 ip2location,正如您的查询所建议的那样,您为什么不使用效率更高、速度更快的 BIN 格式?
  • @HankyPanky ip2location.com/databases/px2-ip-country 是正在使用的数据库。我不相信他们有 BIN 格式。
  • @Barmar 不幸的是,已经有一个索引,我开始认为我无法再提高效率了。

标签: php mysql


【解决方案1】:

我们在 BETWEEN 上也遇到过类似的问题。尝试对 UNION 使用两个单独的查询。老实说,我真的不知道为什么这很快,而 BETWEEN 很慢。

SELECT `ip_from` 
FROM `ip2location_proxy`
WHERE '".$ip."' >= ip_from

UNION ALL

SELECT `ip_from` 
FROM `ip2location_proxy`
WHERE '".$ip."' <= ip_to

【讨论】:

    【解决方案2】:

    假设您的索引很好,并且您运行在一个不那么低功率或慢速磁盘访问系统上,那么我建议如下:

    如果您发现自己的白名单范围很大,例如0 - 2147483648,那么您可以先尝试确保该 IP 不在白名单范围内,然后再咨询您的数据库。

    <?php
    if($ip > 2147483648)
    {
        // consult the ip2location_proxy table
    }
    

    另外,查看https://www.ip2location.com/databases/px2-ip-country 上的示例数据,也许您可​​以尝试删除不是ip_fromip_to 的不需要的列

    【讨论】:

    • 不幸的是,索引基本上从 0 开始。不过,这是一个很好的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 2016-02-04
    • 2010-09-28
    • 2011-04-09
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    相关资源
    最近更新 更多