0

В приложении rails я пытаюсь и потрудился добавить fts в postgres для существующих данных. Вот что я сделал:
Решение Postgresql 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, по-прежнему приветствуется.

+0

Получите необработанный SQL, который Rails запускается из журнала Rails или из журнала PostgreSQL после установки 'log_statement = 'all''. Затем запустите его с помощью 'explain analysis', чтобы получить тайминги и планы. Вставьте результаты в блоки с отступом в вашем вопросе и, если возможно, также вставьте ссылки на копии планов на http://explain.depesz.com/ (полезный инструмент визуализации плана). См. Http://stackoverflow.com/tags/postgresql-performance/info. \ –

+0

Также - вы действительно пытаетесь выполнить полнотекстовый поиск по названиям компаний? Если да, то чего вы пытаетесь достичь - пример запросов и результатов, где вы думаете, что это будет полезно. –

ответ

0

Почему это медленнее?

Я готов поспорить, что он выполняет последовательное сканирование в обоих случаях, а преобразование tsvector медленнее, чем соответствие шаблону.

Какова наилучшая практика для заполнения столбца tsvector для существующих данных?

Вам необходимо создать индексы, которые PostgreSQL может использовать для операций, таких как перекрывающиеся элементы. Индексы Btree (по умолчанию) не дают вам этого. Вам нужен индекс GIN или GIST (большая разница в этом случае заключается в том, что в этом выборе есть компромисс производительности чтения/записи). Также PostgreSQL не будет знать, что он может использовать индекс в вашем случае, потому что вы не запрашиваете индексированный столбец. Вместо этого вам нужен функциональный индекс. Так что вам нужно сделать что-то вроде:

CREATE INDEX company_name_idx_fts ON companies USING GIN (to_tsvector(name, 'English')); 

Затем вы можете отсканировать выход этой функции от вашего полнотекстового поиска в запросе.