3

2 つのモデル オブジェクトがあります。

  • イベント
  • 会場

イベントには会場があります。会場には 1..* イベントを含めることができます。

会場には場所、緯度と経度があり、私はこれを Geokit Rails プラグインで使用しています。これらのモデルは Rails では次のようになります。

class Event < ActiveRecord::Base
  belongs_to :venue
  acts_as_mappable :through => :venue
end

class Venue < ActiveRecord::Base
  has_many :events
  acts_as_mappable  
end

とても簡単です!ここで、クエリを実行したいと思います。特定の地域から数マイル以内にあるすべてのイベントを検索したいと考えています。Geokit API を調べたところ、Event の :through 関連付けで mappable を使用できることがわかりました。イベントで geokit finder を呼び出すことができるはずです! すばらしい (上でわかるように、acts_as_mappable :through をイベントに追加しました)。

これが私のActiveRecordクエリです:

Event.find(:all, :origin => [lat, lng], :select => 'title', :within => 5, :limit => 10)

生成された SQL は次のとおりです。


SELECT `events`.`id` AS t0_r0, `events`.`title` AS t0_r1, `events`.`description` AS t0_r2,
 `events`.`created_at` AS t0_r3, `events`.`updated_at` AS t0_r4, `events`.`venue_id` AS 
t0_r5, `events`.`event_detail_id` AS t0_r6, `events`.`event_detail_type` AS t0_r7, 
`venues`.`id` AS t1_r0, `venues`.`name` AS t1_r1, `venues`.`lat` AS t1_r2, `venues`.`lng` 
AS t1_r3, `venues`.`created_at` AS t1_r4, `venues`.`updated_at` AS t1_r5 FROM `events` LEFT
 OUTER JOIN `venues` ON `venues`.id = `events`.venue_id WHERE 
(((venues.lat>51.4634898826039 AND venues.lat>51.5533406301823 AND venues.lng>-
0.197713629915149 AND venues.lng<-0.053351862714855)) AND 
((ACOS(least(1,COS(0.898991438708539)*COS(-0.00219095974226756)*COS(RADIANS(venues.lat))*COS(RADIANS(venues.lng))
 COS(0.898991438708539)*SIN(-
0.00219095974226756)*COS(RADIANS(venues.lat))*SIN(RADIANS(venues.lng))
 SIN(0.898991438708539)*SIN(RADIANS(venues.lat))))*6376.77271)
 <= 5)) LIMIT 10

ああ。さて、これは実行にかなりの時間がかかります。これは単なる計算ではありません。パフォーマンスに重大な問題があると思います。デスクトップで実行するのに 2 秒かかります。しかし、それに取り掛かると、ここに私の不満があります:

  • パフォーマンスを向上させるために、ActiveRecord の検索クエリで SELECT ステートメントを使用しようとしたことがわかります。他のすべてのフィールドではなく、一致するこれらのイベントのタイトルを知りたいだけです。しかし、クエリは通過し、Event からすべてを SELECT します! 「t1_r1」のように、私がよく知らない奇妙なエイリアスを使用しています。したがって、これは明らかに問題です。

さらに、このクエリは、Venues のみに対して実行される (つまり、JOIN を使用しない) 場合、10 ミリ秒未満で実行されます。この会場検索を最初に実行し、次にイベントに対して結合を実行する方法はありますか? 結合は 2 つのテーブル全体で行う必要があると思います。その後で初めて、ジオコーディング部分が入り、データセットがスリム化されます。

この問題を解決するための助けをいただければ幸いです (これは非営利プロジェクトです)。モデルは非常にシンプルだと思いますが、大騒ぎせずにこれを行うことができるはずですか?

前もって感謝します!

(編集: この投稿の初期のバージョンでは、私は愚かでした。Limit は問題なく機能し、ビューが壊れていたため、その部分を削除するように編集しました。)

4

1 に答える 1

4

Rails Active Recordのeager loadingacts_as_mappable機能を利用しているようです。熱心な読み込みを開始すると、引数は無視され、テーブル/モデルから特定の列を指定できなくなります。あなたの場合、これはへの引数のために起こっていると思います。through 引数なしで動作させることはできますか? ソースコードをいつでも調べて、他にできる調整がないかどうかを確認することもできます.:select:through=>:venueacts_as_mappable

于 2009-10-28T23:27:49.393 に答える