Чому б ви індексували text_pattern_ops у текстовому стовпчику?


18

Сьогодні Сім баз даних за сім тижнів познайомили мене з індексами кожного оператора.

Ви можете проіндексувати рядки для зразка, що відповідає попереднім запитам, створивши text_pattern_opsіндекс класу операторів, якщо значення індексуються в малі регістри.

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

Ми використовували це, text_pattern_opsтому що заголовок є текстовим типом. Якщо вам потрібно індексувати VARCHARS, символи або назв, використовуйте відповідний оп: varchar_pattern_ops, bpchar_pattern_ops, і name_pattern_ops.

Я вважаю, що приклад дуже заплутаний. Чому корисно це робити?

Якщо стовпець є текстовим типом, чи не будуть інші типи (varchar, char, ім'я) передаватися тексту перед тим, як використовуватись як значення пошуку?

Як цей індекс поводиться інакше, ніж один, який використовує оператор за замовчуванням?

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

1
Це пов'язане питання може бути корисним
Ервін

Спасибі, Ервіне. Ваша відповідь на це питання була дуже корисною при дослідженні ідей у ​​книзі.
Iain Samuel McLean Elder

Відповіді:


20

Документація часто дає відповідь на подібні запитання. Як і в цьому випадку :

Оператор класи text_pattern_ops, varchar_pattern_ops та bpchar_pattern_ops підтримують індекси B-дерева для типів тексту, varchar та char відповідно. Відмінність від класів операторів за замовчуванням полягає в тому, що значення порівнюються строго за символами, а не відповідно до правил співставлення, характерних для місцевості. Це робить ці класи операторів придатними для використання в запитах, що містять вирази відповідності шаблону (регулярні вирази LIKE або POSIX), коли база даних не використовує стандартний "C" локал. Як приклад, ви можете проіндексувати стовпчик varchar таким чином:

CREATE INDEX test_index ON test_table (col varchar_pattern_ops);

Зауважте, що ви також повинні створити індекс з класом операторів за замовчуванням, якщо ви хочете, щоб запити, що включають звичайні <, <=,> або> = порівняння, щоб використовувати індекс. Такі запити не можуть використовувати операторські класи xxx_pattern_ops . (Звичайні порівняння рівності можуть використовувати ці класи операторів.) Можна створити декілька індексів у одному стовпчику з різними класами операторів.

Документація продовжує говорити:

Якщо ви використовуєте локальну мову C, вам не потрібні операторські класи xxx_pattern_ops, оскільки індекс із класом оператора за замовчуванням може використовуватися для запитів на відповідність шаблону в мові C.

Ви можете перевірити свою локальність наступним чином (швидше за все, це буде UTF8, а не "C"):

postgres=> show lc_collate;
 lc_collate
-------------
 en_GB.UTF-8

Ага! Я читав це, але важко було це дотримуватися, тому не приймав його. Скажіть, корисність корисної text_pattern_opsзалежності залежить від місцевості? Схоже, це піде на користь мені, оскільки мій локальний код - "en_US.UTF-8" (а не "C"), тому запити шаблонів не можуть використовувати індекс за замовчуванням.
Ієн Самуель Маклін Старший

Саме так. Я додам (але це лише припущення), що для даних, що знаходяться всередині основних символів ASCII, клас операторів за замовчуванням такий же хороший - принаймні я бачу запити з LIKE "щось%", використовуючи такі індекси.
dezso

5
@dezso: Якщо ви бачили LIKEзапит, використовуючи звичайний індекс b-дерева, то db повинен використовувати Cлокаль. Або індекс визначається за допомогою COLLATE "POSIX"(або COLLATE "C"), і запит визначає відповідність COLLATION. При будь-якому іншому порівнянні порядок індексу не відповідає правилам локалі та тому не може бути використаний для відповідності шаблонів.
Ервін Брандстеттер

1
@ErwinBrandstetter Мені потрібно підтвердити, ти маєш рацію.
дезсо

1
@StopHarmingMonica ви отримаєте правильну відповідь (і немає помилок), просто запит буде повільніше, не в змозі використовувати індекс.
dezso
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.