2

アプリの検索機能に pg_search gem を使用しています。pg_search を追加する前に、Postgres データベースのテーブルに 130,000 行のデータを既に追加していました。検索を実行すると、時間がかかりすぎます。つまり、約 16000 ミリ秒かかります。

Railscasts Episode343 Full-Text Search in PostgreSQL をフォローしています

pg_search のモデルのコードは次のとおりです。

include PgSearch
pg_search_scope :search, :against => [:applicant, :generic_name, :trade_name, :description],
using: {tsearch: {dictionary: "english"}},
ignoring: :accents

def self.text_search(query)
    if query.present?
        rank = <<-RANK
            ts_rank(to_tsvector(generic_name), plainto_tsquery(#{sanitize(query)})) +
            ts_rank(to_tsvector(trade_name), plainto_tsquery(#{sanitize(query)}))+
            ts_rank(to_tsvector(description), plainto_tsquery(#{sanitize(query)})) +
            ts_rank(to_tsvector(applicant), plainto_tsquery(#{sanitize(query)})) 
        RANK
        where("generic_name @@ :q or trade_name @@ :q or description @@ :q or applicant @@ :q", q: query)
    else
        all
    end
end

そして、私のサーバー出力は次のとおりです。

  Parameters: {"utf8"=>"✓", "query"=>"intraocular lenses"}
  Parameters: {"utf8"=>"✓", "query"=>"intraocular lenses"}
  Rendered layouts/_search.html.erb (1.5ms)
  Rendered layouts/_search.html.erb (1.5ms)
  Rendered medicaldevices/index.html.erb within layouts/application (16535.9ms)
  Rendered medicaldevices/index.html.erb within layouts/application (16535.9ms)
  Rendered layouts/_header.html.erb (1.8ms)
  Rendered layouts/_header.html.erb (1.8ms)
  Rendered layouts/_footer.html.erb (0.1ms)
  Rendered layouts/_footer.html.erb (0.1ms)
Completed 200 OK in 16574ms (Views: 60.3ms | ActiveRecord: 16510.7ms)
Completed 200 OK in 16574ms (Views: 60.3ms | ActiveRecord: 16510.7ms)

インデックス作成用の移行ファイルは次のとおりです

class AddSearchIndexToMedicaldevices < ActiveRecord::Migration

 def up
     execute "create index generic_name on medicaldevices using gin(to_tsvector('english',     generic_name))"
    execute "create index trade_name on medicaldevices using gin(to_tsvector('english', trade_name))"
    execute "create index description on medicaldevices using gin(to_tsvector('english', description))"
    execute "create index applicant on medicaldevices using gin(to_tsvector('english', applicant))"
  end

  def down
    execute "drop index generic_name"
    execute "drop index trade_name"
    execute "drop index description"
    execute "drop index applicant"
  end

end
4

2 に答える 2

3

これがあなたの答えだと思います(http://www.postgresql.org/docs/8.3/static/textsearch-tables.html

12.2.2. 索引の作成

GIN インデックス (セクション 12.9) を作成して、テキスト検索を高速化できます。

CREATE INDEX pgweb_idx ON pgweb USING gin(to_tsvector('english', body));

to_tsvector の 2 引数バージョンが使用されていることに注意してください。構成名を指定するテキスト検索関数のみが、式インデックス (セクション 11.7) で使用できます。これは、インデックスの内容が default_text_search_config の影響を受けないようにする必要があるためです。それらが影響を受けると、異なるエントリに異なるテキスト検索構成で作成された tsvector が含まれる可能性があり、どれがどれであるかを推測する方法がないため、インデックスの内容に一貫性がなくなる可能性があります。そのようなインデックスを正しくダンプして復元することは不可能です。

上記のインデックスでは 2 引数バージョンの to_tsvector が使用されているため、同じ構成名を持つ 2 引数バージョンの to_tsvector を使用するクエリ参照のみがそのインデックスを使用します。つまり、WHERE to_tsvector('english', body) @@ 'a & b' はインデックスを使用できますが、WHERE to_tsvector(body) @@ 'a & b' は使用できません。これにより、インデックス エントリの作成に使用されたのと同じ構成でのみインデックスが使用されるようになります。

于 2013-10-11T09:39:41.633 に答える