Sql 为什么这种基于范围的查询速度要快得多

Sql 为什么这种基于范围的查询速度要快得多,sql,optimization,range,Sql,Optimization,Range,在工作中,我们对具有以下结构的表进行了查询: 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; 在我们的dev数据库中的oracle10上,根据传入的ip_num,返回

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

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;
在我们的dev数据库中的oracle10上,根据传入的ip_num,返回一行大约需要17秒。在我们的beefier live系统上,可能需要5-6秒的时间,这仍然太慢,无法实时完成,我们需要通过后台作业来选择

不太理想,尤其是我们的实时系统确实需要ip详细信息

所使用的索引类型是一个标准的BTREE索引,跨越ip_-from和ip_-to。我们研究了很多事情,试图加快这一进程,例如。我们最终没有应用它,因为它需要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_from和ip_to之间没有重叠范围

然而,我没有准备好第二个查询的速度有多快。dev数据库上的时间从17秒减少到了0.007秒

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


我的问题是:为什么第二个查询即使使用子选择也要快得多

性能提高明显。这是因为在ip_-from上有一个索引,所以maxip_-from可以在固定时间内获得,因为正如您所知,索引会对值进行排序。由于在btree上进行二进制搜索,范围也很容易计算


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

即使存在组合索引,这是否正确?Wes:DB引擎不知道ip_to永远不小于ip_from。@Gabe统计引擎不会发现这一点吗?我想我会问几个与此查询相关的不同问题。我非常确定索引统计信息仅按每列保存。您是否尝试过单独的索引而不是组合索引?explain命令是否会告诉您原因?@Thomas Padron McCarthy我们对旧版本的查询执行了此操作。综合指数更快。我们打算针对新查询使用单个索引进行测试@nate c-我觉得解释计划没有多大用处。我是开发人员,不是DBA。如果我在工作中把这两个解释计划都放进问题中,会有用吗?