PostgreSQL: RUM индексы

Индекс GIN позволяет выполнять быстрый полнотекстовый поиск, используя типы tsvector и tsquery, но с таким индексом связан ряд проблем:

  • Медленное ранжирование. Для ранжирования необходима информация о позициях, но в индексе GIN не сохраняется информация о позициях лексем. Поэтому после сканирования индекса необходимо провести ещё одно сканирование собственно данных, чтобы получить позиции лексем.
  • Медленный поиск фраз с индексом GIN. Эта проблема связана с предыдущей, так как для осуществления поиска фраз необходима информация о позициях.
  • Медленное упорядочивание по меткам времени. Индекс GIN не может сохранять вместе с лексемами никакую дополнительную информацию, поэтому это требует дополнительного сканирования данных.

Для решения этих проблем был создан RUM-индекс, который сохраняет дополнительную информацию в дереве идентификаторов. В частности, он сохраняет информацию о позиции лексем или метки времени.

Недостаток RUM состоит в том, что он строится и изменяется медленнее, чем GIN. Это связано с тем, что помимо ключей в индексе сохраняется дополнительная информация, и с тем, что RUM использует унифицированный WAL.

Для устновки RUM нужен PostgreSQL 9.6 или новее.

Типичная процедура установки такова:

git clone https://github.com/postgrespro/rum
cd rum
make USE_PGXS=1
sudo make USE_PGXS=1 install
make USE_PGXS=1 installcheck
psql DB -c "CREATE EXTENSION rum;"

Допустим, у нас есть таблица:

CREATE TABLE test_rum(t text, a tsvector);

CREATE TRIGGER tsvectorupdate
BEFORE UPDATE OR INSERT ON test_rum
FOR EACH ROW EXECUTE PROCEDURE
tsvector_update_trigger('a', 'pg_catalog.english', 't');

INSERT INTO test_rum(t) VALUES ('The situation is most beautiful');
INSERT INTO test_rum(t) VALUES ('It is a beautiful');
INSERT INTO test_rum(t) VALUES ('It looks like a beautiful place');

Чтобы создать индекс RUM, необходимо создать расширение:

CREATE EXTENSION rum;

Затем мы можем создать новый индекс:

CREATE INDEX rumidx ON test_rum USING rum (a rum_tsvector_ops);

Выполняем следующие запросы:

SELECT t, a <=> to_tsquery('english', 'beautiful | place') AS rank
    FROM test_rum
    WHERE a @@ to_tsquery('english', 'beautiful | place')
    ORDER BY a <=> to_tsquery('english', 'beautiful | place');
                t                |   rank
---------------------------------+-----------
 The situation is most beautiful | 0.0303964
 It is a beautiful               | 0.0303964
 It looks like a beautiful place | 0.0607927
(3 rows)

SELECT t, a <=> to_tsquery('english', 'place | situation') AS rank
    FROM test_rum
    WHERE a @@ to_tsquery('english', 'place | situation')
    ORDER BY a <=> to_tsquery('english', 'place | situation');
                t                |   rank
---------------------------------+-----------
 The situation is most beautiful | 0.0303964
 It looks like a beautiful place | 0.0303964
(2 rows)

Более подбробную информацию можно найти в документации.

 

19.03.2017









 
архив

подписка