В последние несколько дней я сталкивался с полнотекстовым поиском в postgres, и меня немного смущает индексация при поиске по нескольким столбцам.
В Postgres документах говорить о создании ts_vector
индекса на сцепленных столбцах, например , так:
CREATE INDEX pgweb_idx ON pgweb
USING gin(to_tsvector('english', title || ' ' || body));
который я могу искать так:
... WHERE
(to_tsvector('english', title||' '||body) @@ to_tsquery('english', 'foo'))
Однако, если бы я хотел иногда искать только заголовок, иногда просто тело, а иногда и то и другое, мне потребовалось бы 3 отдельных индекса. И если я добавлю в третий столбец, это может быть 6 индексов и так далее.
Альтернатива, которую я не видел в документах, - это просто индексировать два столбца по отдельности, а затем просто использовать обычный WHERE...OR
запрос:
... WHERE
(to_tsvector('english', title) @@ to_tsquery('english','foo'))
OR
(to_tsvector('english', body) @@ to_tsquery('english','foo'))
Сравнительный анализ двух строк на ~ 1 миллион строк, по-видимому, практически не имеет различий в производительности.
Итак, мой вопрос:
Почему я хотел бы объединить индексы, как это, а не просто индексировать столбцы по отдельности? Каковы преимущества / недостатки обоих?
Мое лучшее предположение состоит в том, что если бы я знал заранее, я бы хотел когда-либо искать оба столбца (никогда не один за раз), мне понадобился бы только один индекс, объединяющий, которые используют меньше памяти.
источник
title
вbody
и затем индексирование, которое даст большую ценность, хотя я открыт для исправления. Я бы, наверное, просто занялся их индексацией по отдельности. Кроме того, если это был какой-то дурацкий случай, который почему-то требовал от вас объединения, то, я думаю, вы могли бы просто выполнить запрос ad-hoc.Ответы:
Нет, вам не нужны отдельные индексы. Используйте функцию весов. Это просто ярлык, к которому вы можете обратиться. Вы можете иметь до четырех меток для запроса (AD).
Возможно, вы захотите объединить tsvector, так что вы можете отдельно применить веса к ним, а затем сложить их вместе:
источник
На самом деле альтернативой было бы использовать где с OR , а не AND .
Если у вас есть указатель на tsvector (тело + заголовок), и вы ищете в нем, искомые слова могут быть в заголовке ИЛИ в теле.
Также - при тестировании убедитесь, что у вас есть разумное количество строк в таблице.
Простейший случай, который должен показать хорошую разницу: найти два слова - одно из которых, скорее всего, будет в заголовке. а другой - это очень вероятно, чтобы быть в организме. Но убедитесь, что не так много строк, которые соответствуют обоим критериям. Например, у вас может быть 30% слова «depesz» в теле. У вас также есть ~ 30% шанс иметь "mysql" в заголовке. Но наличие «depesz and mysql» в любом из полей в одном ряду очень маловероятно. А потом проверь производительность с такими показателями.
источник