Dlaczego indeksowałbyś text_pattern_ops w kolumnie tekstowej?

18

Dzisiaj Siedem baz danych w siedmiu tygodniach zapoznało mnie z indeksami poszczególnych operatorów.

Możesz indeksować ciągi znaków dla wzorca pasującego do poprzednich zapytań, tworząc text_pattern_opsindeks klasy operatora, o ile wartości są indeksowane małymi literami.

CREATE INDEX moves_title_pattern ON movies (
    (lower(title) text_pattern_ops);

Użyliśmy, text_pattern_opsponieważ tytuł jest typu tekstowego. Jeśli trzeba indeks varchars, znaków lub nazw, użyj pokrewnych ops: varchar_pattern_ops, bpchar_pattern_ops, i name_pattern_ops.

Uważam ten przykład za bardzo mylący. Dlaczego warto to zrobić?

Jeśli kolumna zawiera tekst, to czy inne typy (varchar, char, name) nie będą rzutowane na tekst przed użyciem jako wartości wyszukiwania?

Jak ten indeks zachowuje się inaczej niż indeks używający domyślnego operatora?

CREATE INDEX moves_title_pattern ON movies (lower(title));
Iain Samuel McLean Elder
źródło
1
To pokrewne pytanie może być pomocne: dba.stackexchange.com/questions/10694/…
Erwin Brandstetter
Dzięki, Erwin. Twoja odpowiedź na to pytanie była bardzo pomocna przy badaniu pomysłów zawartych w książce.
Iain Samuel McLean Starszy

Odpowiedzi:

20

Dokumentacja często daje odpowiedź na takie pytania. Podobnie jak w tym przypadku :

Klasy operatora text_pattern_ops, varchar_pattern_ops i bpchar_pattern_ops obsługują indeksy B-drzewa odpowiednio dla typów text, varchar i char. Różnica w stosunku do domyślnych klas operatorów polega na tym, że wartości są porównywane ściśle znak po znaku, a nie zgodnie z lokalnymi regułami zestawiania. To sprawia, że te klasy operatorów są odpowiednie do stosowania w zapytaniach zawierających wyrażenia pasujące do wzorca (wyrażenia regularne LIKE lub POSIX), gdy baza danych nie używa standardowych ustawień regionalnych „C”. Na przykład możesz zaindeksować kolumnę varchar w następujący sposób:

CREATE INDEX test_index ON test_table (col varchar_pattern_ops);

Pamiętaj, że powinieneś również utworzyć indeks z domyślną klasą operatora, jeśli chcesz, aby zapytania obejmujące zwykłe porównania <, <=,> lub> = korzystały z indeksu. Takie zapytania nie mogą wykorzystywać klas operatora xxx_pattern_ops . (Jednak zwykłe porównania równości mogą korzystać z tych klas operatorów.) Możliwe jest utworzenie wielu indeksów w tej samej kolumnie z różnymi klasami operatorów.

Dokumentacja mówi dalej:

Jeśli używasz ustawień regionalnych C, nie potrzebujesz klas operatora xxx_pattern_ops, ponieważ indeks z domyślną klasą operatora nadaje się do zapytań dopasowujących wzorce w ustawieniach regionalnych C.

Możesz sprawdzić swoje ustawienia regionalne w następujący sposób (prawdopodobnie jest to UTF8 zamiast „C”):

postgres=> show lc_collate;
 lc_collate
-------------
 en_GB.UTF-8
dezso
źródło
Aha! Przeczytałem to, ale trudno mi było je śledzić, więc nie zrozumiałem. Czy powiedziałbyś, że użyteczna przydatność text_pattern_opszależy od lokalizacji? Wygląda na to, że byłoby to dla mnie korzystne, ponieważ moje ustawienia regionalne to „en_US.UTF-8” (nie „C”), więc zapytania wzorców nie mogą używać domyślnego indeksu.
Iain Samuel McLean Starszy
Dokładnie. Dodałbym (ale to tylko spekulacje), że przy danych pozostających w podstawowych znakach ASCII domyślna klasa operatora jest równie dobra - przynajmniej widzę zapytania z LIKE „coś%” przy użyciu takich indeksów.
dezso
5
@dezso: Jeśli widziałeś LIKEzapytanie przy użyciu zwykłego indeksu b-drzewa, to db musi używać Custawień regionalnych. Lub indeks jest zdefiniowany za pomocą COLLATE "POSIX"(lub COLLATE "C"), a zapytanie określa dopasowanie COLLATION. W przypadku każdego innego sortowania kolejność indeksu nie jest zgodna z regułami ustawień regionalnych, a zatem nie można go używać do dopasowywania wzorców.
Erwin Brandstetter
1
@ErwinBrandstetter Muszę potwierdzić, masz rację.
dezso,
1
@StopHarmingMonica otrzymasz poprawną odpowiedź (i nie ma błędu), tylko zapytanie będzie prawdopodobnie wolniejsze, nie będzie w stanie korzystać z indeksu.
dezso