【问题标题】:Efficient lookup in a range table范围表中的高效查找
【发布时间】:2013-10-17 11:53:49
【问题描述】:

我有一个包含组织名称的 160 万个 IP 范围的表。 IP 地址被转换为整数。表格形式为:

我有一个需要转换为组织名称的 2000 个唯一 IP 地址(例如 321223、531223、...)的列表。

我将转换表加载为 mysql 表,并在 IP_fromIP_to 上具有索引。我遍历了 2000 个 IP 地址,每个 IP 地址运行一个查询,15 分钟后报告仍在运行。 我正在使用的查询是

select organization from iptable where ip_addr BETWEEN ip_start AND ip_end

有没有更有效的方法来进行批量查找?如果这是一个好的解决方案,我会用我的手指。如果有人有特定于 Ruby 的解决方案,我想提一下我正在使用 Ruby。

【问题讨论】:

  • 你想在(IP_from, IP_to)上创建一个R-Tree(空间)索引。
  • 你使用了哪些索引?
  • 我们需要更多信息,例如模式和查询。我们还需要知道为什么 Ruby 和 Rails 是标签。

标签: mysql sql ruby


【解决方案1】:

鉴于您已经在 ip_start 上建立了索引,这是最好的使用方法,假设您希望每个 IP 进行一次访问(在此示例中为 1234):

select organization from (
    select ip_end, organization
    from iptable
    where ip_start <= 1234
    order by ip_start desc
    limit 1
) subqry where 1234 <= ip_end

这将使用您的索引开始扫描,该扫描会因为limit 1 而立即停止。成本应该只略高于简单索引访问的成本。当然,这种技术依赖于ip_startip_end 定义的范围永远不会重叠的事实。

您的原始方法的问题在于,mysql 不知道此约束,只能使用索引来确定从哪里开始或停止(它认为)它需要的扫描,以便为您的查询找到所有匹配项。

【讨论】:

  • 你先生,是 mysql(sql) 神。使用索引和我的原始问题中的查询,我发现 1) 9 位或更少的 IP 地址(例如 248082010)花费了大约 40 毫秒。 2) 超过 10 亿的 IP 地址,即 10 位数字(如 1823194021),需要大约 600 毫秒,这就是扼杀性能的原因。使用您的查询,一切都需要 0.5 毫秒。哇。
  • 谢谢@gitb,但如果我是神,世界将是万神殿;-) 你介意我把你的问题的标题改成“有效查找范围表”吗? (或者也许你有一个更好的标题)。这将朝着“在 Stack Overflow 中高效查找”的方向发展
【解决方案2】:

进行此类查找的最有效方法可能是将要查找的地址列表加载到数据库中的临时表中,并使用 SQL 连接查找交集,而不是使用单独的地址检查每个地址SQL 语句。

在任何情况下,您都需要在 (IP_from, IP_to) 上有一个索引。

【讨论】:

  • 很可能,我的 2000 个 IP 地址都不会出现在查找表中。它们将位于 fromto 字段之间。所以我不知道如何加入。
  • 你可以写 JOIN ON ip &gt;= ip_from AND ip &lt;= ip_to 可能不如使用 = 的连接效率高,但使用适当的索引也不会差很多。
  • @Joni,什么“正确的索引”可以告诉 mysql 只有一条记录可以匹配给定ip 的条件?
  • 你会得到所有的匹配,@Walter。但是,如果没有重叠范围,则每个 IP 最多只能得到一个结果。
  • @Joni,我的理解是,在给定的表上,一次只能使用一个索引,而(ip_from, ip_to)上的多个索引只能用于查找所有ip &gt;= ip_from ,因此需要扫描来检查ip &lt;= ip_to。或者有没有比这更好的方法(除了我的解决方案?)我的问题是真实的,而不是修辞问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-21
  • 1970-01-01
  • 2017-06-21
  • 2018-06-05
  • 1970-01-01
相关资源
最近更新 更多