如何优化此IP到位置查找查询?

时间:2011-09-26 19:00:30

标签: mysql database performance optimization

UPDATE tracker SET t_loc_id=(SELECT cb_loc_id FROM city_blocks WHERE INET_ATON(t_ip) BETWEEN cb_start_ip_num AND cb_end_ip_num LIMIT 1);

tracker中有大约300K记录,city_blocks中有大约360万条记录。它现在已经运行了30多分钟。

我已经在cb_start_ip_numcb_end_ip_num上找到了唯一的索引。

我可以用任何方式加快速度吗?


好的,我让它运行了大约2个小时,它只做了大约9K的记录。

2 个答案:

答案 0 :(得分:3)

在上限列(cb_end_ip_num)上创建索引,并找到该值大于或等于给定值的第一行。

SELECT * FROM city_blocks WHERE cb_end_ip_num >= 123456789 LIMIT 1

我已经将它用于maxmind,并且效果非常好。

答案 1 :(得分:1)

http://jcole.us/blog/archives/2007/11/24/on-efficiently-geo-referencing-ips-with-maxmind-geoip-and-mysql-gis/

我将我的IP范围转换为多边形并添加了空间索引,如上文所述,然后运行我的更新查询:

UPDATE tracker JOIN city_blocks ON mbrcontains(cb_ip_poly, pointfromwkb(point(inet_aton(track_ip),0))) SET t_loc_id=cb_loc_id

第一次在45秒内运行,第二次运行8秒,相对于另一个查询将花费的估计10小时到4天。

该文章还提到了blockhead的解决方案,但它仍然非常缓慢。无法弄清楚为什么...我不知道我的索引是否被破坏(我尝试重建它们)或者它不喜欢在子查询或其他东西?

说到子查询......这个解决方案在使用子查询时效果不佳。我认为子查询会更快,因为我可以添加限制1,它不必将所有内容都加入到所有内容中,但似乎并非如此。技术上没有限制,它将不得不继续搜索以查看IP是否属于其他可能的匹配/范围,但我想这在这种情况下并不重要,因为所有内容都已正确编入索引并且只有1个存储桶可以覆盖到。