搜索速度太慢.如何使用 gem 在 rails 应用程序中重新索引 postgres 数据库pg_search



我正在使用pg_search gem 到我的应用程序中进行搜索功能。在添加pg_search之前,我已经将 130,000 行数据添加到 Postgres 数据库的表中。现在,当我运行搜索时,它花费的时间太长,即大约 16000 毫秒。

我正在关注 Railscasts 第 343 集 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

这是你的答案,我想(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));

请注意,使用的是 2 参数版本的 to_tsvector。只有指定配置名称的文本搜索函数才能在表达式索引中使用(第 11.7 节(。这是因为索引内容必须不受default_text_search_config的影响。如果它们受到影响,索引内容可能不一致,因为不同的条目可能包含使用不同文本搜索配置创建的 tsvector,并且无法猜测哪个是哪个。不可能正确转储和恢复这样的索引。

由于上面的索引中使用了 to_tsvector 的双参数版本,因此只有使用具有相同配置名称的 2 参数版本的 to_tsvector 的查询引用才会使用该索引。也就是说,WHERE to_tsvector('english', body( @@ 'a & b' 可以使用索引,但 WHERE to_tsvector(body( @@ 'a & b' 不能。这可确保索引仅与用于创建索引条目的相同配置一起使用。

塞尔吉奥,我按照你提到的方式,它奏效了。我不得不将上面的旧代码更改为以下内容:

where("to_tsvector('english', generic_name) @@ plainto_tsquery(:q) or 
       to_tsvector('english', trade_name) @@ plainto_tsquery(:q) or 
       to_tsvector('english', description) @@ plainto_tsquery(:q) or 
       to_tsvector('english', applicant)@@ plainto_tsquery(:q)", q: query).order("#{rank} DESC")

我不得不添加planto_tsquery(q(来搜索多词搜索。谢谢!

最新更新