FTS nie obsługuje LIKE
Uprzednio zaakceptowane odpowiedź była błędna. Wyszukiwanie pełnotekstowe z indeksami pełnotekstowymi nie jest w ogóle dla LIKE
operatora, ma własne operatory i nie działa dla dowolnych ciągów znaków. Opiera się na słowach opartych na słownikach i podstawach. To robi support dopasowanie prefiksu dla słów , ale nie z LIKE
operatorem:
Indeksy Trigram dla LIKE
Zainstaluj dodatkowy moduł, pg_trgm
który zapewnia klasy operatorów dla indeksów trygramowych GIN i GiST do obsługi wszystkich wzorców LIKE
iILIKE
, a nie tylko zakotwiczonych w lewo:
Przykładowy indeks:
CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);
Lub:
CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops);
Przykładowe zapytanie:
SELECT * FROM tbl WHERE col LIKE '%foo%'; -- leading wildcard
SELECT * FROM tbl WHERE col ILIKE '%foo%'; -- works case insensitively as well
Trygramy? A co z krótszymi strunami?
Słowa z mniej niż 3 literami w indeksowanych wartościach nadal działają. Instrukcja:
Uważa się, że każde słowo ma dwie spacje z przedrostkiem i jedną spację z sufiksem podczas określania zestawu trygramów zawartych w ciągu.
A wzorce wyszukiwania zawierające mniej niż 3 litery? Instrukcja:
W przypadku wyszukiwania zarówno przy LIKE
użyciu wyrażeń regularnych, jak i przy wyszukiwaniu z użyciem wyrażeń regularnych należy pamiętać, że wzorzec bez trygramów, które można wyodrębnić, zdegeneruje się do pełnego skanowania indeksu.
Oznacza to, że skanowanie indeksów indeksów / bitmap nadal działa (plany zapytań dla przygotowanej instrukcji nie zepsują się), po prostu nie da ci to lepszej wydajności. Zwykle nie ma dużej straty, ponieważ 1- lub 2-literowe łańcuchy nie są selektywne (więcej niż kilka procent dopasowań w tabeli bazowej), a obsługa indeksu nie poprawiłaby wydajności na początku, ponieważ pełne skanowanie tabeli jest szybsze.
text_pattern_ops
do dopasowywania prefiksów
W przypadku wzorców zakotwiczonych w lewo (bez wiodących symboli wieloznacznych) uzyskuje się optimum z odpowiednią klasą operatora dla indeksu btree: text_pattern_ops
lubvarchar_pattern_ops
. Obie wbudowane funkcje standardowego Postgres, nie są potrzebne żadne dodatkowe moduły. Podobna wydajność, ale znacznie mniejszy indeks.
Przykładowy indeks:
CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);
Przykładowe zapytanie:
SELECT * FROM tbl WHERE col LIKE 'foo%'; -- no leading wildcard
Lub , jeśli powinieneś uruchomić swoją bazę danych z ustawieniem regionalnym `` C '' (efektywnie nie ustawień regionalnych), to wszystko i tak jest sortowane według kolejności bajtów, a zwykły indeks btree z domyślną klasą operatora załatwia sprawę.
Więcej szczegółów, wyjaśnienia, przykłady i linki w tych powiązanych odpowiedziach na dba.SE:
pg_trgm
potrzebujesz ciągu zapytania o długości co najmniej 3 znaków, na przykładfo%
nie trafiłbym w indeks, ale zamiast tego wykonałby skanowanie. Coś do zapamiętania.Możliwe, że te szybkie to zakotwiczone wzorce z rozróżnianiem wielkości liter, które mogą używać indeksów. tj. nie ma symbolu wieloznacznego na początku łańcucha dopasowania, więc executor może użyć skanowania zakresu indeksu. ( odpowiedni komentarz w dokumentacji jest tutaj ) Lower i ilike również utracą możliwość korzystania z indeksu, chyba że specjalnie utworzysz indeks w tym celu (zobacz indeksy funkcjonalne ).
Jeśli chcesz wyszukać ciąg w środku pola, powinieneś przejrzeć indeksy pełnotekstowe lub trygramowe . Pierwsza z nich jest w rdzeniu Postgres, druga jest dostępna w modułach Contrib.
źródło
Możesz zainstalować Wildspeed , inny typ indeksu w PostgreSQL. Wildspeed działa z symbolami wieloznacznymi% word%, nie ma problemu. Wadą jest rozmiar indeksu, który może być duży, bardzo duży.
źródło
Proszę wykonać poniższe zapytanie, aby poprawić wydajność zapytania LIKE w postgresql. utwórz taki indeks dla większych tabel:
źródło
co jest warte, Django ORM zwykle używa
UPPER(text)
dla wszystkichLIKE
zapytań, aby nie rozróżniać wielkości liter,Dodanie indeksu
UPPER(column::text)
znacznie przyspieszyło mój system, w przeciwieństwie do innych rzeczy.Jeśli chodzi o wiodące%, tak, to nie będzie używać indeksu. Zobacz ten blog, aby uzyskać świetne wyjaśnienie:
https://use-the-index-luke.com/sql/where-clause/searching-for-ranges/like-performance-tuning
źródło
Niedawno miałem podobny problem z tabelą zawierającą 200000 rekordów i muszę powtarzać zapytania LIKE. W moim przypadku szukany ciąg został naprawiony. Inne dziedziny były zróżnicowane. Dzięki temu mogłem przepisać:
tak jak
Byłem zachwycony, gdy zapytania wróciły szybko i zweryfikowałem, że indeks jest używany z
EXPLAIN ANALYZE
:źródło
Twoje podobne zapytania prawdopodobnie nie mogą korzystać z utworzonych indeksów, ponieważ:
1) Twoje kryteria LIKE zaczynają się od symbolu wieloznacznego.
2) użyłeś funkcji z kryteriami LIKE.
źródło
Kiedykolwiek używasz klauzuli w kolumnie z funkcjami, np. LIKE, ILIKE, upper, lower itp. Postgres nie weźmie pod uwagę twojego normalnego indeksu. Wykonuje pełne skanowanie tabeli przechodząc przez każdy wiersz i dlatego będzie działać wolno.
Prawidłowym sposobem byłoby utworzenie nowego indeksu zgodnie z zapytaniem. Na przykład, jeśli chcę dopasować kolumnę bez rozróżniania wielkości liter, a moja kolumna to varchar. Wtedy możesz to zrobić w ten sposób.
Podobnie, jeśli twoja kolumna jest tekstem, robisz coś takiego
Podobnie możesz zmienić górną funkcję na dowolną inną, którą chcesz.
źródło