2010-06-04 4 views
0

will_paginate를 사용하여 내 geokit 검색 결과를 페이지 매김했습니다. 에서 다음 will_paginate 전화를 사용할 때 두 배 geokit 쿼리를 수행 기록을 볼 때 코드는하지만, 작동 :Will_paginate 및 geokit misbehavior (double query)

@posts = Post.paginate :page => params[:page], :per_page => 1, 
         :origin => @search, :within => @miles, :include => :user 

이 예상 (단일 쿼리)로 작동 원래 비 페이징 호출입니다 :

당신이 볼 수 있듯이

Processing PostsController#search (for 127.0.0.1 at 2010-06-03 22:10:29) [POST] 
    Parameters: {"commit"=>"Search", "action"=>"search", "authenticity_token"=>"K9Btfu6p7pz2mt+lWH0Fx0O7qj+0QY21JpfgyWT738I=", "controller"=>"posts", "location"=>"new york"} 
Google geocoding. Address: new york. Result: <?xml version="1.0" encoding="UTF-8" ?> 
<kml xmlns="http://earth.google.com/kml/2.0"><Response> 
    <name>new york</name> 
    <Status> 
    <code>200</code> 
    <request>geocode</request> 
    </Status> 
    <Placemark id="p1"> 
    <address>New York, NY, USA</address> 
    <AddressDetails Accuracy="4" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><CountryName>USA</CountryName><AdministrativeArea><AdministrativeAreaName>NY</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>New York</SubAdministrativeAreaName><Locality><LocalityName>New York</LocalityName></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails> 
    <ExtendedData> 
     <LatLonBox north="40.8494506" south="40.5788125" east="-73.7498541" west="-74.2620917" /> 
    </ExtendedData> 
    <Point><coordinates>-74.0059729,40.7142691,0</coordinates></Point> 
    </Placemark> 
</Response></kml> 
    Post Load (0.7ms) SELECT *, 
(ACOS(least(1,COS(0.710598048337988)*COS(-1.2916478932467)*COS(RADIANS(posts.lat))*COS(RADIANS(posts.lng))+ 
COS(0.710598048337988)*SIN(-1.2916478932467)*COS(RADIANS(posts.lat))*SIN(RADIANS(posts.lng))+ 
SIN(0.710598048337988)*SIN(RADIANS(posts.lat))))*3963.19) 
AS distance FROM `posts` WHERE (((posts.lat>40.352844467866 AND posts.lat<41.075693732134 AND posts.lng>-74.4827993840952 AND posts.lng<-73.5291464159048)) AND (
(ACOS(least(1,COS(0.710598048337988)*COS(-1.2916478932467)*COS(RADIANS(posts.lat))*COS(RADIANS(posts.lng))+ 
COS(0.710598048337988)*SIN(-1.2916478932467)*COS(RADIANS(posts.lat))*SIN(RADIANS(posts.lng))+ 
SIN(0.710598048337988)*SIN(RADIANS(posts.lat))))*3963.19) 
<= 25)) LIMIT 0, 1 
    Post Columns (2.4ms) SHOW FIELDS FROM `posts` 
    User Columns (2.2ms) SHOW FIELDS FROM `users` 
    User Load (0.4ms) SELECT * FROM `users` WHERE (`users`.`id` = 1) 
Google geocoding. Address: new york. Result: <?xml version="1.0" encoding="UTF-8" ?> 
<kml xmlns="http://earth.google.com/kml/2.0"><Response> 
    <name>new york</name> 
    <Status> 
    <code>200</code> 
    <request>geocode</request> 
    </Status> 
    <Placemark id="p1"> 
    <address>New York, NY, USA</address> 
    <AddressDetails Accuracy="4" xmlns="urn:oasis:names:tc:ciq:xsdschema:xAL:2.0"><Country><CountryNameCode>US</CountryNameCode><CountryName>USA</CountryName><AdministrativeArea><AdministrativeAreaName>NY</AdministrativeAreaName><SubAdministrativeArea><SubAdministrativeAreaName>New York</SubAdministrativeAreaName><Locality><LocalityName>New York</LocalityName></Locality></SubAdministrativeArea></AdministrativeArea></Country></AddressDetails> 
    <ExtendedData> 
     <LatLonBox north="40.8494506" south="40.5788125" east="-73.7498541" west="-74.2620917" /> 
    </ExtendedData> 
    <Point><coordinates>-74.0059729,40.7142691,0</coordinates></Point> 
    </Placemark> 
</Response></kml> 
    SQL (0.4ms) SELECT count(*) AS count_all FROM `posts` WHERE (((posts.lat>40.352844467866 AND posts.lat<41.075693732134 AND posts.lng>-74.4827993840952 AND posts.lng<-73.5291464159048)) AND (
(ACOS(least(1,COS(0.710598048337988)*COS(-1.2916478932467)*COS(RADIANS(posts.lat))*COS(RADIANS(posts.lng))+ 
COS(0.710598048337988)*SIN(-1.2916478932467)*COS(RADIANS(posts.lat))*SIN(RADIANS(posts.lng))+ 
SIN(0.710598048337988)*SIN(RADIANS(posts.lat))))*3963.19) 
<= 25)) 
Rendering template within layouts/application 

KML/XML과 SQL 쿼리를 두 배로 다음 는

@posts = Post.find(:all, :origin => @search, :within => @miles, :include => :user) 

첫 will_paginate 호출을 사용하여 로그를 출력합니다. 어떤 일이 벌어지고 어떻게 해결할 수 있을지 궁금한가요? 감사!

- 토니

답변

0

실제로 이것은 표준 동작입니다. will_paginate는 먼저 레코드 수를 계산 한 다음 표시되는 페이지 및 페이지의 행 수에 따라 20 행을 검색합니다. 따라서 쿼리가 완전히 동일하지 않습니다.

페이지 수를 표시하려면 개수가 필요합니다.

will_paginate 쿼리가 숫자를 20 (또는 페이지 크기와 상관없이)으로 제한하고 표시되는 쿼리가 완전히 동일하지 않으므로 로깅이 완전히 이해가되지 않습니다. 예를 들어 조건이 달라집니다.

+0

설명해 주셔서 감사합니다. 그건 의미가 있습니다. 결과를 캐시 할 수있는 방법이 있습니까? 나는 두 가지 두려움을 가지고있다 : 1. 구글/야후 API 한계들 2. 구글 API 호출 + SQL 쿼리를 생성하는 데 걸리는 시간. 내 로컬 컴퓨터에서는 단일 쿼리를 완료하는 데 약 200 + ms가 소요됩니다. will_paginate가 사용되면 300-430 + ms가됩니다. 의견이 있으십니까? – slythic

+0

200ms가 많이 보입니다. 위도/경도 열에 인덱스가 정의되어 있습니까? 또한 테두리 상자를 검색하면 성능이 향상 될 수 있습니다. 자세한 내용은 여기 : http://geokit.rubyforge.org/readme.html,하지만 당신도 그걸 읽었을 것입니다. 레일스는 동일한 쿼리를 자동으로 캐시하지만 그러한 쿼리는 결코 존재하지 않습니다. – nathanvda