2013-10-02 3 views
1

Ruby 1.9, 지오 코더 gem을 사용합니다. 내 컨트롤러가 다음 쿼리는 :Ruby Geocoder 근처가 느립니다.

# 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 

문제는 longitudelatitude상의 계산을 수행하는 nearbys에있다. longitudelatitude 열에 이미 색인을 추가했지만 개선되지 않았습니다.

어떻게 향상시킬 수 있습니까?

P/S : 쿼리 속도에 영향을주지 않는 관련없는 조건을 제거했습니다.

+0

에는 'shop_type'에 대한 색인이 있습니까? – Kyle

+0

@ 카일 예, 이미 있습니다. – Victor

+0

Postgres 9.3에서 98.4ms에서 실행되는 매우 유사한 쿼리가 있습니다. 어떤 종류의 데이터베이스를 사용하고 있습니까? –

답변

0

이것은 가장 정확하고 세련된 해결책은 아니지만 단순히 수학을 조금 퍼지하는 것이 아닙니다. 그냥 작은 (< 5백마일) 거리를 처리하는 경우 당신은 정말 털이 대원 공식을 사용할 필요가 없습니다

.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]) 

:이 같은 짓을 SELECT 절을 작성할 수 있습니다. 결국 계산 비용의 일부만으로 거의 ~ 거의 같은 결과를 얻게 될 것입니다.