Зачем вам индексировать 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.

Я нахожу пример действительно запутанным. Почему это полезно?

Если столбец имеет тип text, не будут ли другие типы (varchar, char, name) преобразованы в текст перед использованием в качестве значения для поиска?

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

CREATE INDEX moves_title_pattern ON movies (lower(title));
Иэн Сэмюэл Маклин Старейшина
источник
1
Этот связанный вопрос может быть полезен
Эрвин Брандштеттер
Спасибо, Эрвин. Ваш ответ на этот вопрос был очень полезен при исследовании идей в книге.
Иэн Сэмюэль Маклин Старейшина

Ответы:

20

Документация часто дает вам ответ на такие вопросы. Как и в этом случае тоже:

Классы операторов text_pattern_ops, varchar_pattern_ops и bpchar_pattern_ops поддерживают индексы B-дерева для типов text, 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
Dezso
источник
Ага! Я читал это, но мне было трудно следовать, поэтому не принимал это. Вы сказали бы, что полезность text_pattern_opsзависит от локали? Похоже, это принесет мне пользу, потому что моя локаль 'en_US.UTF-8' (не 'C'), поэтому запросы шаблонов не могут использовать индекс по умолчанию.
Иэн Сэмюэл Маклин, старейшина
Точно. Я хотел бы добавить (но это только предположение), что с данными, остающимися внутри основных символов ASCII, класс операторов по умолчанию так же хорош - по крайней мере, я вижу запросы с LIKE '%%', использующие такие индексы.
Дезсо
5
@dezso: Если вы видели LIKEзапрос с использованием простого индекса b-дерева, то база данных должна использовать Cлокаль. Или индекс определяется с помощью COLLATE "POSIX"(или COLLATE "C"), а в запросе указывается соответствие COLLATION. При любом другом сопоставлении порядок индекса не соответствует правилам локали и поэтому не может использоваться для сопоставления с образцом.
Эрвин Брандштеттер
1
@ ErwinBrandstetter Я должен подтвердить, что вы правы.
Дезсо
1
@StopHarmingMonica вы получите правильный ответ (и без ошибок), просто запрос будет медленнее, не имея возможности использовать индекс.
Дезсо