【问题标题】:Why is this range based query so much quicker为什么这个基于范围的查询要快得多
【发布时间】:2011-05-15 06:39:11
【问题描述】:

在工作中,我们对具有以下结构的表进行了查询:

ip_from(number), ip_to(number), country, city, state, isp, latitude, longitude.

这个表有大约 610 万行。

为了找出给定 IP 地址的详细信息,我们使用了如下查询:

SELECT * 
  FROM Ip2location
WHERE
  :ip_num BETWEEN ip_from AND ip_to;

在我们的开发数据库中的 Oracle 10 上,这大约需要 17 秒才能返回一行,具体取决于传入的 ip_num。在我们更强大的实时系统上,它可能需要 5-6 秒,这仍然太慢了实时,我们需要通过后台作业来选择它。

理想,尤其是当我们的实时系统确实需要 IP 详细信息时。

使用的索引类型是标准 BTREE 索引,涵盖 ip_fromip_to。我们研究了很多东西以尝试加快速度,例如range partitioning。我们最终没有应用它,因为它需要 Oracle Enterprise。我们还研究了增加表的并发性,但没有明显效果。

无论如何,当我早上喝咖啡时,我意识到我认为可以通过运行以下查询来提高性能:(这是凭记忆,可能有几个错误。而且我们选择了单个字段而不是全部)

SELECT * 
  FROM ip2location
WHERE 
  ip_from = (
    SELECT max(ip_from)
      FROM ip2location
      WHERE ip_from <= :ip_num
  )
AND
  ip_to >= ip_num;

这适用于我们的数据集,因为 ip_fromip_to 之间没有重叠范围。

但是我没有准备好第二个查询的速度有多快。我们开发数据库的时间从 17 秒减少到 0.007 秒。

这对我来说毫无意义。我预计性能会有所提高,但不会那么多。数据库统计不应该发现没有重叠并进行相应的优化吗?还必须有一种公认的更快的方法来使用范围进行选择?

我的问题是:为什么即使使用子选择,第二个查询也会这么快?

【问题讨论】:

  • 您是否尝试过单独的索引而不是组合索引?
  • 解释命令不会告诉你原因吗?
  • @Thomas Padron-McCarthy 我们为旧版本的查询所做的。组合索引更快。我们打算针对新查询使用单个索引进行测试。 @nate c - 我在解释计划中没有发现太多用处。我是开发人员而不是 DBA。如果在工作中我将两个解释计划都放入问题中会有用吗?

标签: sql optimization range


【解决方案1】:

性能提升很明显。这是因为 ip_from 上有一个索引,所以 max(ip_from) 可以在恒定时间内获得,因为如您所知,索引会对值进行排序。由于对 btree 的二分搜索,范围也很容易计算。

而在上一个查询中,必须对所有数据进行表扫描以计算范围界限

【讨论】:

  • 即使有组合索引也是如此吗?
  • Wes:DB 引擎不知道ip_to 永远不会小于ip_from
  • @Gabe 统计引擎不会发现吗?我想我会问几个与此查询相关的不同问题。
  • 我很确定索引统计信息只保留在每列的基础上。
猜你喜欢
  • 2018-01-04
  • 1970-01-01
  • 1970-01-01
  • 2020-10-14
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
  • 2018-01-28
  • 1970-01-01
相关资源
最近更新 更多