12.2. ТаблиÑÑ Ð¸ индекÑÑ #
РпÑедÑдÑÑем Ñазделе пÑиводилиÑÑ Ð¿ÑимеÑÑ, коÑоÑÑе показÑвали, как можно вÑполниÑÑ ÑопоÑÑавление Ñ Ð¿ÑоÑÑÑми ÑекÑÑовÑми конÑÑанÑами. Ð ÑÑом Ñазделе показÑваеÑÑÑ, как Ð½Ð°Ñ Ð¾Ð´Ð¸ÑÑ ÑекÑÑ Ð² ÑаблиÑе, возможно Ñ Ð¿Ñименением индекÑов.
12.2.1. ÐоиÑк в ÑаблиÑе #
ÐолноÑекÑÑовÑй поиÑк можно вÑполниÑÑ, не пÑименÑÑ Ð¸Ð½Ð´ÐµÐºÑ. СледÑÑÑий пÑоÑÑой запÑÐ¾Ñ Ð²ÑÐ²Ð¾Ð´Ð¸Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²Ð¾Ðº (title) каждой ÑÑÑоки, ÑодеÑжаÑей Ñлово friend в поле body:
SELECT title
FROM pgweb
WHERE to_tsvector('english', body) @@ to_tsquery('english', 'friend'); ÐÑи ÑÑом Ñакже бÑдÑÑ Ð½Ð°Ð¹Ð´ÐµÐ½Ñ ÑвÑзаннÑе Ñлова, Ñакие как friends и friendly, Ñак как вÑе они ÑводÑÑÑÑ Ðº одной ноÑмализованной лекÑеме.
Рпоказанном вÑÑе пÑимеÑе Ð´Ð»Ñ ÑазбоÑа и ноÑмализаÑии ÑÑÑоки Ñвно вÑбиÑаеÑÑÑ ÐºÐ¾Ð½ÑигÑÑаÑÐ¸Ñ english. ХоÑÑ Ð¿Ð°ÑамеÑÑÑ, задаÑÑие конÑигÑÑаÑиÑ, можно опÑÑÑиÑÑ:
SELECT title
FROM pgweb
WHERE to_tsvector(body) @@ to_tsquery('friend');Такой запÑÐ¾Ñ Ð±ÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑ ÐºÐ¾Ð½ÑигÑÑаÑиÑ, заданнÑÑ Ð² паÑамеÑÑе default_text_search_config.
Ð ÑледÑÑÑем более Ñложном пÑимеÑе вÑбиÑаÑÑÑÑ Ð´ÐµÑÑÑÑ Ð´Ð¾ÐºÑменÑов, изменÑннÑÑ
поÑледними, Ñо Ñловами create и table в полÑÑ
title или body:
SELECT title
FROM pgweb
WHERE to_tsvector(title || ' ' || body) @@ to_tsquery('create & table')
ORDER BY last_mod_date DESC
LIMIT 10; ЧÑÐ¾Ð±Ñ Ð½Ð°Ð¹Ñи ÑÑÑоки, ÑодеÑжаÑие NULL в одном из полей, нÑжно воÑполÑзоваÑÑÑÑ ÑÑнкÑией coalesce, но здеÑÑ Ð¼Ñ Ð¾Ð¿ÑÑÑили ÐµÑ Ð²ÑÐ·Ð¾Ð²Ñ Ð´Ð»Ñ ÐºÑаÑкоÑÑи.
ХоÑÑ Ñакие запÑоÑÑ Ð±ÑдÑÑ ÑабоÑаÑÑ Ð¸ без индекÑа, Ð´Ð»Ñ Ð±Ð¾Ð»ÑÑинÑÑва пÑиложений ÑкоÑоÑÑÑ Ð±ÑÐ´ÐµÑ Ð½ÐµÐ¿Ñиемлемой; ÑÑÐ¾Ñ Ð¿Ð¾Ð´Ñ Ð¾Ð´ ÑекомендÑеÑÑÑ ÑолÑко Ð´Ð»Ñ Ð½ÐµÑегÑлÑÑного поиÑка и динамиÑеÑкого ÑодеÑжимого. ÐÐ»Ñ Ð¿ÑакÑиÑеÑкого пÑÐ¸Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»Ð½Ð¾ÑекÑÑового поиÑка обÑÑно ÑоздаÑÑÑÑ Ð¸Ð½Ð´ÐµÐºÑÑ.
12.2.2. Создание индекÑов #
ÐÐ»Ñ ÑÑкоÑÐµÐ½Ð¸Ñ ÑекÑÑового поиÑка Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ ÑоздаÑÑ Ð¸Ð½Ð´ÐµÐºÑ GIN (Ñм. Раздел 12.9):
CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector('english', body)); ÐамеÑÑÑе, ÑÑо здеÑÑ Ð¸ÑполÑзÑеÑÑÑ ÑÑнкÑÐ¸Ñ to_tsvector Ñ Ð´Ð²ÑÐ¼Ñ Ð°ÑгÑменÑами. РвÑÑажениÑÑ
, опÑеделÑÑÑиÑ
индекÑÑ, можно иÑполÑзоваÑÑ ÑолÑко ÑÑнкÑии, в коÑоÑÑÑ
Ñвно задаÑÑÑÑ Ð¸Ð¼Ñ ÐºÐ¾Ð½ÑигÑÑаÑии ÑекÑÑового поиÑка (Ñм. Раздел 11.7). ÐÑо обÑÑÑнÑеÑÑÑ Ñем, ÑÑо ÑодеÑжимое индекÑа не должно завиÑеÑÑ Ð¾Ñ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ Ð¿Ð°ÑамеÑÑа default_text_search_config. РпÑоÑивном ÑлÑÑае ÑодеÑжимое индекÑа Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð½ÐµÐ°ÐºÑÑалÑнÑм, еÑли ÑазнÑе его ÑлеменÑÑ tsvector бÑдÑÑ ÑоздаваÑÑÑÑ Ñ ÑазнÑми конÑигÑÑаÑиÑми ÑекÑÑового поиÑка и нелÑÐ·Ñ Ð±ÑÐ´ÐµÑ Ð¿Ð¾Ð½ÑÑÑ, какÑÑ Ð¸Ð¼ÐµÐ½Ð½Ð¾ иÑполÑзоваÑÑ. ÐÑгÑÑзиÑÑ Ð¸ воÑÑÑановиÑÑ Ñакой Ð¸Ð½Ð´ÐµÐºÑ Ð±ÑÐ´ÐµÑ Ð½ÐµÐ²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾.
Так как пÑи Ñоздании индекÑа иÑполÑзовалаÑÑ Ð²ÐµÑÑÐ¸Ñ to_tsvector Ñ Ð´Ð²ÑÐ¼Ñ Ð°ÑгÑменÑами, ÑÑÐ¾Ñ Ð¸Ð½Ð´ÐµÐºÑ Ð±ÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ ÑолÑко в запÑоÑаÑ
, где to_tsvector вÑзÑваеÑÑÑ Ñ Ð´Ð²ÑÐ¼Ñ Ð°ÑгÑменÑами и во вÑоÑом пеÑедаÑÑÑÑ Ð¸Ð¼Ñ Ñой же конÑигÑÑаÑии. То еÑÑÑ, WHERE to_tsvector('english', body) @@ 'a & b' ÑÐ¼Ð¾Ð¶ÐµÑ Ð¸ÑполÑзоваÑÑ ÑÑÐ¾Ñ Ð¸Ð½Ð´ÐµÐºÑ, а WHERE to_tsvector(body) @@ 'a & b' â неÑ. ÐÑо гаÑанÑиÑÑеÑ, ÑÑо Ð¸Ð½Ð´ÐµÐºÑ Ð±ÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ ÑолÑко Ñ Ñой конÑигÑÑаÑией, Ñ ÐºÐ¾ÑоÑой ÑоздавалиÑÑ ÐµÐ³Ð¾ ÑлеменÑÑ.
ÐÐ½Ð´ÐµÐºÑ Ð¼Ð¾Ð¶Ð½Ð¾ ÑоздаÑÑ Ð±Ð¾Ð»ÐµÐµ ÑложнÑм обÑазом, опÑеделив Ð´Ð»Ñ Ð½ÐµÐ³Ð¾ Ð¸Ð¼Ñ ÐºÐ¾Ð½ÑигÑÑаÑии в дÑÑгом ÑÑолбÑе ÑаблиÑÑ, напÑимеÑ:
CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector(config_name, body));
где config_name â Ð¸Ð¼Ñ ÑÑолбÑа в ÑаблиÑе pgweb. Так можно ÑоÑ
ÑаниÑÑ Ð¸Ð¼Ñ ÐºÐ¾Ð½ÑигÑÑаÑии, ÑвÑзанной Ñ ÑлеменÑом индекÑа, и, Ñаким обÑазом, имеÑÑ Ð² одном индекÑе ÑлеменÑÑ Ñ ÑазнÑми конÑигÑÑаÑиÑми. ÐÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾, напÑимеÑ, когда в коллекÑии докÑменÑов Ñ
ÑанÑÑÑÑ Ð´Ð¾ÐºÑменÑÑ Ð½Ð° ÑазнÑÑ
ÑзÑкаÑ
. Рв ÑÑом ÑлÑÑае в запÑоÑаÑ
должен иÑполÑзоваÑÑÑÑ ÑÐ¾Ñ Ð¶Ðµ Ð¸Ð½Ð´ÐµÐºÑ (Ñ Ñаким же обÑазом задаваемой конÑигÑÑаÑией), напÑимеÑ, Ñак: WHERE to_tsvector(config_name, body) @@ 'a & b'.
ÐндекÑÑ Ð¼Ð¾Ð³ÑÑ ÑоздаваÑÑÑÑ Ð´Ð°Ð¶Ðµ по обÑÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ ÑÑолбÑов:
CREATE INDEX pgweb_idx ON pgweb USING GIN (to_tsvector('english', title || ' ' || body));ÐÑÑ Ð¾Ð´Ð¸Ð½ ваÑÐ¸Ð°Ð½Ñ â ÑоздаÑÑ Ð¾ÑделÑнÑй ÑÑÐ¾Ð»Ð±ÐµÑ tsvector, в коÑоÑом ÑоÑ
ÑаниÑÑ ÑезÑлÑÑÐ°Ñ to_tsvector. ЧÑÐ¾Ð±Ñ ÑÑÐ¾Ñ ÑÑÐ¾Ð»Ð±ÐµÑ Ð°Ð²ÑомаÑиÑеÑки ÑинÑ
ÑонизиÑовалÑÑ Ñ Ð¸ÑÑ
однÑми даннÑми, он ÑоздаÑÑÑÑ ÐºÐ°Ðº Ñ
ÑанимÑй генеÑиÑÑемÑй ÑÑолбеÑ. СледÑÑÑий пÑÐ¸Ð¼ÐµÑ Ð¿Ð¾ÐºÐ°Ð·ÑваеÑ, как можно подгоÑовиÑÑ Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑаÑии обÑединÑнное ÑодеÑжимое ÑÑолбÑов title и body, пÑименив ÑÑнкÑÐ¸Ñ coalesce Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ Ð¶ÐµÐ»Ð°ÐµÐ¼Ð¾Ð³Ð¾ ÑезÑлÑÑаÑа, даже когда один из ÑÑолбÑов NULL:
ALTER TABLE pgweb
ADD COLUMN textsearchable_index_col tsvector
GENERATED ALWAYS AS (to_tsvector('english', coalesce(title, '') || ' ' || coalesce(body, ''))) STORED;ÐаÑем Ð¼Ñ ÑоздаÑм Ð¸Ð½Ð´ÐµÐºÑ GIN Ð´Ð»Ñ ÑÑкоÑÐµÐ½Ð¸Ñ Ð¿Ð¾Ð¸Ñка:
CREATE INDEX textsearch_idx ON pgweb USING GIN (textsearchable_index_col);
ТепеÑÑ Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ бÑÑÑÑо вÑполнÑÑÑ Ð¿Ð¾Ð»Ð½Ð¾ÑекÑÑовÑй поиÑк:
SELECT title
FROM pgweb
WHERE textsearchable_index_col @@ to_tsquery('create & table')
ORDER BY last_mod_date DESC
LIMIT 10;Ð¥Ñанение вÑÑиÑленного вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа в оÑделÑном ÑÑолбÑе даÑÑ ÑÑд пÑеимÑÑеÑÑв. Ðо-пеÑвÑÑ
, Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа в запÑоÑаÑ
не нÑжно Ñвно ÑказÑваÑÑ Ð¸Ð¼Ñ ÐºÐ¾Ð½ÑигÑÑаÑии ÑекÑÑового поиÑка. Ðак показано в вÑÑепÑиведÑнном пÑимеÑе, в ÑÑом ÑлÑÑае запÑÐ¾Ñ Ð¼Ð¾Ð¶ÐµÑ Ð·Ð°Ð²Ð¸ÑеÑÑ Ð¾Ñ default_text_search_config. Ðо-вÑоÑÑÑ
, поиÑк вÑполнÑеÑÑÑ Ð±ÑÑÑÑее, Ñак как Ð´Ð»Ñ Ð¿ÑовеÑки ÑооÑвеÑÑÑÐ²Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
индекÑÑ Ð½Ðµ нÑжно повÑоÑно вÑполнÑÑÑ to_tsvector. (ÐÑо акÑÑалÑно болÑÑе Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑов GiST, Ñем Ð´Ð»Ñ GIN; Ñм. Раздел 12.9.) С дÑÑгой ÑÑоÑонÑ, ÑÑ
ÐµÐ¼Ñ Ñ Ð¸Ð½Ð´ÐµÐºÑом по вÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¿ÑоÑе ÑеализоваÑÑ Ð¸ она позволÑÐµÑ ÑÑкономиÑÑ Ð¼ÐµÑÑо на диÑке, Ñак как пÑедÑÑавление tsvector не Ñ
ÑаниÑÑÑ Ñвно.