Производительность Postgres tsearch при первом запросе

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

Словарь можно найти здесь: http://www.sai.msu.su/~megera/postgres/gist/tsearch/V2/ (ispell-german-component.tar.gz).

Диктовки были преобразованы в UTF8, и я использовал следующий скрипт для добавления конфигурации в базу данных:

DROP TEXT SEARCH DICTIONARY IF EXISTS german_bon_ispell CASCADE;
DROP TEXT SEARCH DICTIONARY IF EXISTS german_bon_stem CASCADE;

CREATE TEXT SEARCH CONFIGURATION german_bon (copy=german);

CREATE TEXT SEARCH DICTIONARY german_bon_stem (
TEMPLATE = snowball,
  Language = german,
  StopWords = german
);

CREATE TEXT SEARCH DICTIONARY german_bon_ispell (
TEMPLATE = ispell,
  dictfile = german,
  afffile = german,
  StopWords = german
);

ALTER TEXT SEARCH CONFIGURATION german_bon
  ALTER MAPPING FOR
    asciiword,word,numword,numhword,hword_asciipart,hword_part,hword_numpart
  WITH german_bon_ispell, german_bon_stem;

Сам словарь прекрасно работает, но при каждом новом соединении / сеансе первый запрос с использованием этой конфигурации занимает 1-2 секунды. Каждое следующее ~1-3 мс.

Этот эффект также заметен для словаря английского языка, но не настолько радикальный:

db=# \timing
Timing is on.
db=# select ts_debug('english', 'Book');
                               ts_debug
-----------------------------------------------------------------------
 (asciiword,"Word, all ASCII",Book,{english_stem},english_stem,{book})
(1 row)

Time: 6,977 ms
db=# select ts_debug('english', 'Book');
                               ts_debug
-----------------------------------------------------------------------
 (asciiword,"Word, all ASCII",Book,{english_stem},english_stem,{book})
(1 row)

Time: 2,258 ms
db=# select ts_debug('german_bon', 'Buch');
                                             ts_debug
---------------------------------------------------------------------------------------------------
 (asciiword,"Word, all ASCII",Buch,"{german_bon_ispell,german_bon_stem}",german_bon_ispell,{buch})
(1 row)

Time: 916,286 ms
db=# select ts_debug('german_bon', 'Buch');
                                             ts_debug
---------------------------------------------------------------------------------------------------
 (asciiword,"Word, all ASCII",Buch,"{german_bon_ispell,german_bon_stem}",german_bon_ispell,{buch})
(1 row)

Time: 1,240 ms
db=#

Единственный обходной путь, о котором я сейчас знаю, - это использование постоянных соединений / пулов соединений, и мы используем для этого pgbouncer. Но это создает некоторые другие проблемы с нашим клиентом (PHP>PDO>Doctrine), который выглядит как проблема с кэшированием.

Есть ли способ уменьшить это "время запуска"? Похоже, что конфигурация загружается / создается для каждого нового соединения, что просто не кажется разумным.

1 ответ

Решение

Это известная проблема - загрузка словаря ispell происходит медленно (он загружается каждый раз, когда словарь используется впервые в сеансе). Одним из хороших решений является объединение сессий. Другое решение заключается в использовании общего словаря ispell - расширения, написанного Томасом Вондрой - shared_ispell, но я не знаю, насколько хорошо поддерживается какая-то новая версия PostgreSQL 9.2 и выше - она ​​протестирована на 9.2. Может быть проблема с немецким языком - это проверено с чешским языком.

Другая возможность - использовать немецкий словарь снежного кома - он должен быть значительно быстрее, но результат может быть хуже. Удалите german_bon_ispell из вашей полнотекстовой конфигурации.

Другие вопросы по тегам