1

В базе данных Postgres 9.4, я создал индекс GIN триграмма на столе под названием «человек», который содержит 1514 строк, как показано в следующем:индекс GIN не используется для небольшого стола, когда 0 строк возвращаемой

CREATE INDEX persons_index_name_1 ON persons 
USING gin (lower(name) gin_trgm_ops); 

и а запрос, который ищет подобные имена следующим образом:

select name, last_name from persons where lower(name) % 'thename' 

Итак, я первый выпустил запрос с именем, я заранее знал, что будет иметь подобные матчи, поэтому explain analyze показал, что индекс я создал был использован в этом запросе:

select name, last_name from persons where lower(name) % 'george' 

И результаты были ожидаемые:

-> Bitmap Heap Scan on persons (cost=52.01..58.72 rows=2 width=26) (actual time=0.054..0.065 rows=1 loops=1) 
     Recheck Cond: (lower((name)::text) % 'george'::text) 
     Rows Removed by Index Recheck: 2 
     Heap Blocks: exact=1 
     -> Bitmap Index Scan on persons_index_name_1 (cost=0.00..52.01 rows=2 width=0) (actual time=0.032..0.032 rows=3 loops=1) 
       Index Cond: (lower((name)::text) % 'george'::text) 
... 
Execution time: 1.382 ms" 

Так, из любопытства, я хотел бы видеть, если индекс был использован, когда параметр thename содержал имя, которое не существовало вообще в таблица:

select name, last_name from persons where lower(name) % 'noname' 

Но я видел, что в этом случае индекс не был использован на всех, и время выполнения было выше способом:

-> Seq Scan on persons (cost=0.00..63.72 rows=2 width=26) (actual time=6.494..6.494 rows=0 loops=1) 
     Filter: (lower((name)::text) % 'noname'::text) 
     Rows Removed by Filter: 1514 
... 
Execution time: 7.387 ms 

В качестве теста я попробовал то же самое с индексом GIST, и в обоих случаях использовался индекс, а время выполнения было похоже на первый случай выше.

Я пошел вперед и воссоздал таблицу, но на этот раз вставил 10014 строк; и я видел, что в обоих случаях выше использовался индекс GIN, и время исполнения было лучшим для этих случаев.

Почему индекс GIN не используется, когда указанный выше запрос не возвращает результатов в таблицу с не таким количеством строк (1514 в моем случае)?

ответ

1

триграмма индексы регистронезависимы, тест с:

select 'case' <-> 'CASE' AS ci1 
    , 'case' % 'CASE' AS ci2 
    , 'CASE' <-> 'CASE' AS c1 
    , 'CASE' % 'CASE' AS c2; 

Таким образом, вы можете также просто:

CREATE INDEX persons_index_name_1 ON persons USING gin (name gin_trgm_ops); 

И:

select name, last_name from persons where name % 'thename'; 

Как ваш актуальный вопрос , для небольших таблиц индексный поиск может не платить. Это именно то, что демонстрируют ваши добавленные тесты. И установив, что ничего совпадений может быть дороже, чем найти некоторые совпадения.

Помимо этого, ваши статистические данные о стоимости и/или таблице могут быть не оптимальными, чтобы позволить Postgres выбрать наиболее подходящие планы запросов.

Ожидаемые номера расходов перевести на много более высокую фактическую стоимость для последовательного сканирования, чем для сканирования индекса растрового изображения. Вы можете переоценить стоимость сканирования индекса по сравнению с последовательным сканированием. random_page_costcpu_index_tuple_cost) может быть установлен слишком высоким и effective_cache_size слишком низкий.

+0

Большое спасибо Эрвин. Очень ценю тот факт, что вы упомянули, что индексы триграмм нечувствительны к регистру. Это решает большой вопрос, который у меня был. Я обязательно посмотрю на «random_page_cost» и «cpu_index_tuple_cost». –