3

我订阅了 ip2location 服务,它为我提供了这种格式的 SQL 表

FromIP (int), ToIP(int), lat, long, city  etc etc 

我想解析我的访问日志并对所有用户进行分类访问日志有 IP 地址和用户 ID(比如说)

所以我运行一个查询

select city from ip2location where FromIP <= $ipAsInt  AND ToIP => $ipAsInt

但这对于我必须解析的数百万条记录来说太长了。我想这一定是 ip2location 的一个非常常见的用法。可以优化结构吗?

4

5 回答 5

2

您也可以像这样编写查询

select city,ToIP from ip2location where ToIP >= $ipAsInt order by ToIP limit 1

这将比以前快很多。

您还可以索引 ToIP 列以提高性能。

正如ip2location建议的那样,您可以使用创建 FromIP 和 ToIP 的复合主键

ALTER TABLE ip2location ADD PRIMARY KEY(FromIP,ToIP);
于 2013-12-03T13:17:58.510 回答
2

事实证明,您可以做得比LIMIT 1!

此处的 ip2location 网站上,它显示了使用子查询的速度如何提高几个数量级

SELECT * FROM ( SELECT * FROM ip2location_db3 WHERE ip_to >= INET_ATON('8.8.8.8') LIMIT 1 ) AS tmp WHERE ip_from <= INET_ATON('8.8.8.8')

在我对 MacBook 的测试中,不同的 IP 地址花费了不同的时间。性能最差的 IP 地址具有以下性能:

  • 14s 使用BETWEENLIMIT 1
  • 300msBETWEEN使用LIMIT 1
  • 2ms 使用上面的子选择

那是 7000 倍快!

于 2017-04-26T22:39:41.530 回答
1

FromIP确保您的表格在和上建立索引ToIP。检查您的数据库,它是否具有完整的内存表等功能以供查找。

您可能希望将所有 IP 加载到另一个表中,并在一个 SQL 语句中将城市连接到该表,而不是为您拥有的每个 IP 发送一条语句。这将比一次只做一个 IP 快得多。

于 2013-07-12T09:48:38.653 回答
1

如果您可以在 perl 中编写代码,则可以使用 Memoization http://perldoc.perl.org/Memoize.html ,这样后续使用相同 IP 的调用就不会在数据库中查找。

如果您愿意失去一些准确性,进一步的优化将是使用 IP 的 CLass C 组件进行查询。

对 from_ip 和 to_ip 以及复合索引进行索引也会有所帮助。

于 2013-07-12T09:53:27.610 回答
0

我发现最简单的方法是按 ips 的排序顺序查找当我查找 IP 时,我也选择了最后一个 IP

像这样

从 ip2location 中选择城市,ToIP,其中 FromIP <= $ipAsInt AND ToIP => $ipAsInt

现在,当我必须查找下一个地址时,如果下一个 ip 已经小于最后一个 $ToIP,我不会查询该表

对于每 1000 次查找,我在这里只查询大约 80 次。

于 2013-07-22T12:13:31.763 回答