Railsアプリでは、既存のデータのpostgresにftsを追加しようとしています。これが私がやったことです:
class AddNameFtsIndexToCompanies < ActiveRecord::Migration
def up
execute(<<-'eosql'.strip)
DROP INDEX IF EXISTS index_companies_name;
CREATE INDEX index_companies_name
ON companies
USING gin( (to_tsvector('english', "companies"."name")) );
eosql
execute(<<-'eosql'.strip)
ALTER TABLE companies ADD COLUMN name_tsv tsvector;
CREATE TRIGGER tsv_name_update
BEFORE INSERT OR UPDATE ON companies FOR EACH ROW
EXECUTE PROCEDURE tsvector_update_trigger(name_tsv, 'pg_catalog.english', name);
CREATE INDEX index_companies_fts_name ON companies USING GIN (name_tsv);
eosql
end
def down
execute(<<-'eosql'.strip)
DROP INDEX IF EXISTS index_companies_name
eosql
execute(<<-'eosql'.strip)
DROP INDEX IF EXISTS index_fts_name;
DROP TRIGGER IF EXISTS tsv_name_update ON companies;
ALTER TABLE companies DROP COLUMN name_tsv
eosql
end
end
name_tsv 列の値はまだ空です。しかし、簡単なテストのために、私はこれを試しました:
input_data = "foo"
Company.where(["to_tsvector(companies.name) @@ plainto_tsquery(?)", input_data ])
これと比較してください:
input_data = "foo"
Company.where(["companies.name ilike ? ", "%#{input_data}%"])
そして前者は遅いです。
質問:
1. 遅いのはなぜですか?
2. 既存のデータの tsvector 列を設定するためのベスト プラクティスは何ですか?
私の質問は Rails アプリに関連していますが、一般的には postgresql fts に関するものであるため、postgres 固有のソリューションは引き続き歓迎されます。