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 は問題なく機能し、ビューが壊れていたため、その部分を削除するように編集しました。)