Ruby Geocoder nearbys is slow

放肆的年华 提交于 2019-12-11 13:10:35

问题


Using Rails 3.2, Ruby 1.9, geocoder gem. The following query I have in my controller:

# 1500+ms to load
nearby_shops = (current_shop.nearbys(10, :order => 'overall_rating DESC')
.where(:shop_type => shop_type).includes(:photos, :active_property_list => 
:hotel_image_lists).limit(5))

# SQL
Shop Load (4045.6ms)  SELECT shops.*, 3958.755864232 * 2 * ASIN(SQRT(POWER(
SIN((36.111927 - shops.lat) * PI() / 180 / 2), 2) + COS(36.111927 * PI()
 / 180) * COS(shops.lat * PI() / 180) * POWER(SIN((-115.171229 - shops.lng)
 * PI() / 180 / 2), 2))) AS distance, CAST(DEGREES(ATAN2( RADIANS(shops.lng
 - -115.171229), RADIANS(shops.lat - 36.111927))) + 360 AS decimal) % 360 AS
 bearing FROM `shops` WHERE `shops`.`shop_type` = 'food' AND (shops.lat BETWEEN
 35.96719521688915 AND 36.25665878311085 AND shops.lng BETWEEN
 -115.3503819353204 AND -114.9920760646796 AND 3958.755864232 * 2 * 
ASIN(SQRT(POWER(SIN((36.111927 - shops.lat) * PI() / 180 / 2), 2) + 
COS(36.111927 * PI() / 180) * COS(shops.lat * PI() / 180) * POWER(SIN((
-115.171229 - shops.lng) * PI() / 180 / 2), 2))) <= 10 AND shops.id != 85155)
 ORDER BY overall_rating DESC LIMIT 5
 - shops.lat) * PI() / 180 / 2), 2) + COS(48.8582411618 * PI() / 180) * 
COS(shops.lat * PI() / 180) * POWER(SIN((2.2945044899 - shops.lng) * PI() / 
180 / 2), 2))) <= 100 AND shops.id != 517) ORDER BY distance ASC LIMIT 25
 OFFSET 0

The problem lies in the nearbys which does calculation on the longitude and latitude. I have already added indexes to the longitude and latitude columns, but it doesn't improve anything.

How can I improve this?

P/S: I removed unrelated conditions which doesn't contribute to the speed of the query.


回答1:


This might not be the most exact or elegant solution, but why not just fudge the math a little. You could write a select clause that did something like this:

 .select(["id, name, 69.0975851*sqrt(POWER(shops.lat-?,2) + COS(?*PI()/180)*POWER(shops.lon-?,2)) AS DISTANCE", loc.lat, loc.lat, loc.lon])

You don't really need to use that hairy great circle formula if you're just dealing with small (< 500 mile) distances. You'll end up getting the same ~almost~ answers for a fraction of the computational cost.



来源:https://stackoverflow.com/questions/19143398/ruby-geocoder-nearbys-is-slow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!