Полнотекстовый поиск выполняется медленно по одному редкому слову, но быстро, когда повторяется одно и то же слово? - PullRequest
0 голосов
/ 17 ноября 2018

У меня есть таблица с индексом GIN, похожим на:

CREATE INDEX my_index ON my_table USING GIN (to_tsvector('english', lower(
    (jsondoc->>'StreetAddress') 
    || ' ' || (jsondoc->>'Neighborhood')
    || ' ' || (jsondoc->>'Area')
    || ' ' || (jsondoc->>'CrossStreet')
    || ' ' || (jsondoc->>'Community')
    || ' ' || (jsondoc->>'Complex') )))
where source = 'x';

В моей таблице 2,5 млн строк.

Предположим, я хочу запросить слово banana, которое не очень часто встречается в этом наборе данных. На самом деле он появляется ровно 8 раз.

Теперь вот странная часть.

Этот запрос требует повторения 3 полных секунды для выполнения:

select * from my_table where
(source='x' AND plainto_tsquery('english', 'banana') @@ to_tsvector('english', lower(
    (jsondoc->>'StreetAddress') 
    || ' ' || (jsondoc->>'Neighborhood')
    || ' ' || (jsondoc->>'Area')
    || ' ' || (jsondoc->>'CrossStreet')
    || ' ' || (jsondoc->>'Community')
    || ' ' || (jsondoc->>'Complex') )) AND (jsondoc->>'L_AskingPrice')::real>=250000 AND ((jsondoc->>'L_AskingPrice')::real<=2500000 OR (jsondoc->>'L_asking_price_low')::real<=2500000) AND jsondoc->>
'L_Status' IN ('ACTIVE','BACK ON MARKET') AND iscurrent='true')

, в то время как это выполняется надежно всего за 50 миллисекунд :

select * from my_table where
(source='x' AND plainto_tsquery('english', 'banana banana') @@ to_tsvector('english', lower(
    (jsondoc->>'StreetAddress') 
    || ' ' || (jsondoc->>'Neighborhood')
    || ' ' || (jsondoc->>'Area')
    || ' ' || (jsondoc->>'CrossStreet')
    || ' ' || (jsondoc->>'Community')
    || ' ' || (jsondoc->>'Complex') )) AND (jsondoc->>'L_AskingPrice')::real>=250000 AND ((jsondoc->>'L_AskingPrice')::real<=2500000 OR (jsondoc->>'L_asking_price_low')::real<=2500000) AND jsondoc->>
'L_Status' IN ('ACTIVE','BACK ON MARKET') AND iscurrent='true')

Можете ли вы заметить разницу?

Да: слово банан повторяется во втором запросе. Теперь это только пример. В ходе дополнительного тестирования я обнаружил, что по существу любое отдельное слово занимает много времени (~ 3 секунды), в то время как любой поиск по двойному слову (включая 2 разных слова) выполняется быстро (~ 50 мс).

Последняя версия PostgreSQL (v11).

Что могло вызвать это?

Планы запросов

медленно (одно слово) Slow

Быстро (одно слово повторяется дважды) Fast

...