Пострегістр повнотекстового пошуку з кількома стовпцями, чому concat в індексі, а не під час виконання?


11

Останні кілька днів я натрапив на пошук повного тексту в постграфах, і я трохи не збентежений щодо індексації під час пошуку в декількох стовпцях.

У 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.
swasheck

Ви правильні у своїх здогадах. Я б закликав вас самостійно відповідати, якщо ніхто інший цього не зробить, тут стиль небезпеки.
jcolebrand

Відповіді:


4

Ні, вам не потрібні окремі індекси. Використовуйте функцію ваг. Вони є лише міткою, проти якої можна запитати. Ви можете мати до чотирьох міток для запиту проти (AD).

--search any "field" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick'::tsquery; --true

--search B "field" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick:B'::tsquery; --false

--search B or C "fields" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick:BC'::tsquery; --true

Ви можете об'єднати цвектори, щоб ви могли окремо застосувати до них ваги, а потім скласти їх:

select
  setweight( name_column::tsvector, 'A') || setweight( phone_column::tsvector, 'B');

3

На насправді альтернативи можна було б використовувати , де з OR , а не AND .

Якщо у вас є індекс на tsvector (body + назва), і ви шукаєте в ньому, слова, що шукаються, можуть бути в заголовку АБО в body.

Також - під час тестування переконайтеся, що у вас є достатня кількість рядків у таблиці.

Найпростіший випадок, який повинен виявити хорошу різницю: знайдіть два слова - одне з них, яке, ймовірно, буде в заголовку. а інше - що, швидше за все, буде в організмі. Але переконайтесь, що рядків не так багато, що відповідають обом критеріям. Наприклад - у вас може бути 30% слова "depesz" в тілі. Ви також маєте ~ 30% шансів на тему "mysql". Але мати "depesz і mysql" в будь-якому з полів того ж ряду дуже малоймовірно. А потім перевіряйте продуктивність за допомогою таких індексів.


Ха, добре місце, АБО ІЗ І я оновлю питання. Я зробив це в 1 мільйон рядків - не можна було турбуватися, чекаючи, коли ще вставити :)
latentflip

1
Дякуємо за те, що відмовились від depesz - у нас сьогодні виникає досить багато запитань у postgres, тож я сподіваюся, що ви будете триматися :-)
Джек каже, спробуйте topanswers.xyz

@Jack: не впевнений, що буду - я знайшов stackexchange сайти все менш і менш корисними. Я, як правило, намагаюся отримувати RSS, але на сайтах stackexchange rss є дуже марним - стільки забруднення від видання старих питань.

Я створив RSS - канал для вас тут - ви готові дати що спробувати? Я радий докласти зусиль для фільтрації речей, які вам навряд чи зацікавлять, щоб отримати більше шансів залучити вас на сайт :-)
Джек каже спробувати topanswers.xyz

Джек :) Я кусаю - підписався.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.