【发布时间】: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_from 和 ip_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_from 和 ip_to 之间没有重叠范围。
但是我没有准备好第二个查询的速度有多快。我们开发数据库的时间从 17 秒减少到 0.007 秒。
这对我来说毫无意义。我预计性能会有所提高,但不会那么多。数据库统计不应该发现没有重叠并进行相应的优化吗?还必须有一种公认的更快的方法来使用范围进行选择?
我的问题是:为什么即使使用子选择,第二个查询也会这么快?
【问题讨论】:
-
您是否尝试过单独的索引而不是组合索引?
-
解释命令不会告诉你原因吗?
-
@Thomas Padron-McCarthy 我们为旧版本的查询所做的。组合索引更快。我们打算针对新查询使用单个索引进行测试。 @nate c - 我在解释计划中没有发现太多用处。我是开发人员而不是 DBA。如果在工作中我将两个解释计划都放入问题中会有用吗?
标签: sql optimization range