Shinya Kawaji
kawaj****@gmail*****
2012年 6月 6日 (水) 17:59:41 JST
かわじです
かなり以前のメールの続きで恐縮ですが、ActiveGroonga の場合、スコアを
ソートに指定すると、メモリを消費しすぎないかが気になっているのですが、
お聞きできますでしょうか。
以前のメールで、
> result_set = Groonga["Site"].select
> # ↑が--filter "1"相当
> result_set.select("_score = rand() && false", :syntax => :script)
> # ↑が--scorer "_score = rand()"相当
> result_set.sort(["_score"])
> # ↑が--sortby "_score"相当
>
> 最初に引数もブロックもなしでselectを呼んでいますが、これがポ
> イントです。
>
> groongaでは検索処理の結果を一時テーブル(*)に格納します。実
> は、_scoreカラムがあるのはSiteなどの永続的なテーブルではなく
> 一時テーブルにあります。これは、永続的なテーブルに_scoreを追
> 加すると同時に複数の検索結果に_scoreをつけられないからです。
> 引数もブロックもないselectはこの一時テーブルを作っています。
> 何も条件を指定していないのですべてのレコードが格納されていま
> す。
>
> (*) 一時テーブルとはSiteなど名前がついていない、データベース
> を閉じるとなくなってしまうテーブルのことです。
で、rroongaの場合でのスコアの設定方法を知ることが出来ました。
実際に使っているのは ActiveGroongaなのですが、
class ActiveGroonga::ResultSet
def sort_by_shuffle(opts = {})
create_result_set(
@records.select("_score = rand()", :syntax => :script).sort(
["_score"], opts
)
)
end
end
のように仕込んで、
Site.all.sort_by_shuffle(:limit => 5)
などとしています。
この場合、示してくださった "_score = rand() && false" では正しく取得出来
ず、"_score = rand()" だけを指定しているのですが、以下の引用にある
「呼んでいて結果は使いません」という状態になっていないのではないかと
危惧しています。
> 次に、result_set.selectで--filterに指定できる書式で、各レコー
> ドに適用する式を指定しています。result_set.selectは本来は検
> 索するための処理なのでresult_set.selectの結果も一時テーブル
> になります。しかし、ここでは"_score = rand()"をすべてのレコー
> ドで実行するためだけに呼んでいて結果は使いません(*)。そのた
> め、" && false"を最後につけて1つもレコードがヒットしないよう
> にしています。これで使わない検索結果にレコードが追加されなく
> なります。
>
> (*) result_set.selectの副作用だけが重要ということ。
この場合、処理のたびに余分な結果をメモリに積むことになってしまうのでは
ないかと思い、パフォーマンスに影響が出るのではないかと危惧していますが、
いかがでしょうか。
余計な心配でしたでしょうか。
よろしくお願いします。