Как создать индекс в postgresql для регулярных выражений? - PullRequest
2 голосов
/ 26 февраля 2020

У меня есть таблица product

product_id | desciption                                     
============================================================
322919     | text {add}185{/add} text                       
322920     | text {add}184{/add} text {add}185{/add} text   
322921     | text {add}185{/add} text {add}187{/add} text

sql запрос с как очень медленный

SELECT product_id, desciption 
FROM product 
WHERE LOWER(desciption) like '%{add}185{/add}%'
> Time: 340,159s

Мне нужно только индекс для поиска {add} 185 {/ add} выражений. т.е. нужно сделать индекс для этой таблицы

SELECT product_id, regexp_matches (desciption, '(\{add\}\d+\{\/add\})', 'g') 
FROM product 

возвращает:

product_id | regexp_matches 
================================================================================
322919     | {"{add}185{/add}"}
322920     | {"{add}184{/add}"}
322920     | {"{add}185{/add}"}
322921     | {"{add}185{/add}"}
322921     | {"{add}187{/add}"}
  1. Какой лучше создать индекс для выборки данных?
  2. Какое выражение лучше использовать в "ГДЕ"?

Ответы [ 2 ]

1 голос
/ 26 февраля 2020

Самое простое решение - просто создать индекс pg_trgm .

 create extension pg_trgm;
 create index on product using gin (description gin_trgm_ops);

Затем вы можете использовать тот же запрос, только удалить LOWER и изменить LIKE на ILIKE.

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

create function extract_tokens(text) returns text[] immutable language sql as $$ 
   select array_agg(regexp_matches[1]) from 
      regexp_matches ($1, '\{add\}(\d+)\{\/add\}+','g') 
$$;

Обратите внимание, что я переместил круглые скобки, чтобы они получали только цифры, а не окружающие метки, которые просто кажутся шумом. Тот факт, что были совпадения, свидетельствует о том, что они были там, нам не нужно их видеть.

create index on product using gin (extract_tokens(description))

select * from product where extract_tokens(description) @> ARRAY['185'];
0 голосов
/ 26 февраля 2020

Для лучшего поиска вам нужно создать индекс для столбца 'description'

При использовании лайка, помните только эту подстановочную работу с индексом

SELECT product_id, desciption FROM product WHERE LOWER(desciption) like '{add}185{/add}%'

Так что ваш запрос выше не работает с индексом

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...