Функция подобия Postgres неправильно использует индекс триграммы - PullRequest
0 голосов
/ 13 ноября 2018

У меня есть простая таблица person со столбцом last_name, в которую я добавил индекс GIST с

CREATE INDEX last_name_idx ON person USING gist (last_name gist_trgm_ops);

Согласно документам на https://www.postgresql.org/docs/10/pgtrgm.html, оператор <-> должен использовать этот индекс. Однако, когда я на самом деле пытаюсь использовать этот оператор разницы, используя этот запрос:

explain verbose select * from person where last_name <-> 'foobar' > 0.5;

Я получаю это обратно:

Seq Scan on public.person  (cost=0.00..290.82 rows=4485 width=233)
  Output: person_id, first_name, last_name
  Filter: ((person.last_name <-> 'foobar'::text) < '0.5'::double precision)

И не похоже, что индекс используется. Однако, если я использую оператор % с этой командой:

explain verbose select * from person where last_name % 'foobar';

Кажется, используется индекс:

Bitmap Heap Scan on public.person  (cost=4.25..41.51 rows=13 width=233)
  Output: person_id, first_name, last_name
  Recheck Cond: (person.last_name % 'foobar'::text)
  ->  Bitmap Index Scan on last_name_idx  (cost=0.00..4.25 rows=13 width=0)
        Index Cond: (person.last_name % 'foobar'::text)

Я также заметил, что если я переместу оператор в выбранную часть запроса, индекс снова будет игнорироваться:

explain verbose select last_name % 'foobar' from person;

Seq Scan on public.person  (cost=0.00..257.19 rows=13455 width=1)
  Output: (last_name % 'foobar'::text)

Я упускаю что-то очевидное в том, как функция подобия использует индекс триграмм?

Я использую Postgres 10.5 на OSX.

РЕДАКТИРОВАТЬ 1

По предложению Лоренца я попытался установить enable_seqscan = off, но, к сожалению, запрос с оператором <->, похоже, по-прежнему игнорирует индекс.

show enable_seqscan;
 enable_seqscan
----------------
 off

explain verbose select * from person where last_name <-> 'foobar' < 0.5;

-----------------------------------------------------------------------------------------------------------------------------
 Seq Scan on public.person  (cost=10000000000.00..10000000290.83 rows=4485 width=233)
   Output: person_id, first_name, last_name
   Filter: ((person.last_name <-> 'foobar'::text) < '0.5'::double precision)

1 Ответ

0 голосов
/ 14 ноября 2018

Это нормальное поведение для всех видов индексов.

Первый запрос не в форме, которая может использовать индекс.Для этого условие должно иметь форму

<indexed expression> <operator supported by the index> <quasi-constant>

, где последние выражения остаются постоянными на протяжении сканирования индекса, а оператор возвращает логическое значение.Ваше выражение ´last_name <-> 'foobar'> 0.5` не имеет такой формы.

Оператор <-> должен использоваться в предложении ORDER BY, чтобы иметь возможность использовать индекс.

Третий запрос не использует индекс, поскольку запрос затрагивает все строки таблицы.Индекс не ускоряет оценку выражения, он полезен только для быстрой идентификации подмножества таблицы (или для получения строк в определенном порядке сортировки).

...