У меня есть таблица с индексом 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).
Что могло вызвать это?
Планы запросов
медленно (одно слово)
Быстро (одно слово повторяется дважды)