Ваш запрос в значительной степени оптимальный. Синтаксис не станет намного короче, запрос не станет намного быстрее:
SELECT name
FROM spelers
WHERE name LIKE 'B%' OR name LIKE 'D%'
ORDER BY 1;
Если вы действительно хотите сократить синтаксис , используйте регулярное выражение с ветвями :
...
WHERE name ~ '^(B|D).*'
Или немного быстрее, с классом персонажа :
...
WHERE name ~ '^[BD].*'
Быстрый тест без индекса дает более быстрые результаты, чем SIMILAR TOв любом случае для меня.
С соответствующим индексом B-Tree LIKEвыигрывает эту гонку на порядки.
Прочитайте основы сопоставления с образцом в руководстве .
Индекс для превосходной производительности
Если вас интересует производительность, создайте такой индекс для больших таблиц:
CREATE INDEX spelers_name_special_idx ON spelers (name text_pattern_ops);
Делает такой запрос быстрее на порядок. Особые соображения применяются для порядка сортировки, зависящего от локали. Подробнее о классах операторов читайте в руководстве . Если вы используете стандартную локализацию "C" (большинство людей этого не делают), подойдет простой индекс (с классом оператора по умолчанию).
Такой индекс хорош только для левых якорных паттернов (совпадающих с начала строки).
SIMILAR TOили регулярные выражения с базовыми левосторонними выражениями также могут использовать этот индекс. Но не с ветвями (B|D)или классами символов [BD](по крайней мере, в моих тестах на PostgreSQL 9.0).
Для совпадения триграмм или текстового поиска используются специальные индексы GIN или GiST.
Обзор операторов сопоставления с образцом
LIKE( ~~) прост и быстр, но ограничен в своих возможностях.
ILIKE( ~~*) регистронезависимый вариант.
pg_trgm расширяет поддержку индекса для обоих.
~ (совпадение регулярного выражения) является мощным, но более сложным и может быть медленным для чего-то большего, чем базовые выражения.
SIMILAR TOпросто бессмысленно . Своеобразный полукровка LIKEи регулярные выражения. Я никогда не использую это. Смотри ниже.
% - это оператор «сходства», предоставляемый дополнительным модулемpg_trgm. Смотри ниже.
@@является оператором текстового поиска. Смотри ниже.
pg_trgm - сопоставление триграмм
Начиная с PostgreSQL 9.1, вы можете упростить расширение, pg_trgmчтобы обеспечить поддержку индексов для любого LIKE / ILIKEшаблона (и простых шаблонов регулярных выражений с ~) с использованием индекса GIN или GiST.
Подробности, пример и ссылки:
pg_trgmтакже предоставляет следующие операторы :
% - оператор "сходства"
<%(commutator %>:) - оператор "word_s Similarity" в Postgres 9.6 или более поздней версии
<<%(commutator %>>:) - оператор "strict_word_simility" в Postgres 11 или более поздней версии
Поиск текста
Это специальный тип сопоставления с шаблоном с отдельными типами инфраструктуры и индекса. Он использует словари и основы и является отличным инструментом для поиска слов в документах, особенно для естественных языков.
Сопоставление префиксов также поддерживается:
Так же как поиск фразы начиная с Postgres 9.6:
Рассмотрим введение в руководство и обзор операторов и функций .
Дополнительные инструменты для нечеткого соответствия строк
Дополнительный модуль fuzzystrmatch предлагает еще несколько опций, но производительность, как правило, уступает всем вышеперечисленным.
В частности, различные реализации levenshtein()функции могут быть инструментальными.
Почему регулярные выражения ( ~) всегда быстрее чем SIMILAR TO?
Ответ прост. SIMILAR TOвыражения переписываются внутри регулярных выражений. Таким образом, для каждого SIMILAR TOвыражения есть хотя бы одно более быстрое регулярное выражение (которое позволяет сэкономить на переписывании выражения). Там нет прирост производительности при использовании SIMILAR TO никогда .
А простые выражения, которые можно сделать с помощью LIKE( ~~), в LIKEлюбом случае быстрее .
SIMILAR TOподдерживается только в PostgreSQL, потому что он оказался в ранних версиях стандарта SQL. Они до сих пор не избавились от этого. Но есть планы удалить его и включить вместо него совпадения регулярных выражений - или я так слышал.
EXPLAIN ANALYZEраскрывает это. Попробуйте сами с любым столом!
EXPLAIN ANALYZE SELECT * FROM spelers WHERE name SIMILAR TO 'B%';
раскрывает:
...
Seq Scan on spelers (cost= ...
Filter: (name ~ '^(?:B.*)$'::text)
SIMILAR TOбыл переписан с помощью регулярного выражения ( ~).
Максимальная производительность в данном конкретном случае
Но EXPLAIN ANALYZEраскрывает больше. Попробуйте, с указанным выше индексом:
EXPLAIN ANALYZE SELECT * FROM spelers WHERE name ~ '^B.*;
раскрывает:
...
-> Bitmap Heap Scan on spelers (cost= ...
Filter: (name ~ '^B.*'::text)
-> Bitmap Index Scan on spelers_name_text_pattern_ops_idx (cost= ...
Index Cond: ((prod ~>=~ 'B'::text) AND (prod ~<~ 'C'::text))
Внутренне, с индексом , который не зависит от локали известно ( text_pattern_opsили с помощью локали C) простые выражения лево-якорь переписываются с этими операторами текста шаблона: ~>=~, ~<=~, ~>~, ~<~. Это случай ~, ~~или SIMILAR TOкак.
То же самое верно для индексов varcharтипов с varchar_pattern_opsили charс bpchar_pattern_ops.
Итак, применительно к исходному вопросу, это самый быстрый способ :
SELECT name
FROM spelers
WHERE name ~>=~ 'B' AND name ~<~ 'C'
OR name ~>=~ 'D' AND name ~<~ 'E'
ORDER BY 1;
Конечно, если вам придется искать соседние инициалы , вы можете упростить дальнейшее:
WHERE name ~>=~ 'B' AND name ~<~ 'D' -- strings starting with B or C
Выгода по сравнению с простым использованием ~или ~~крошечная. Если производительность не является вашим главным требованием, вам следует просто придерживаться стандартных операторов - прийти к тому, что у вас уже есть в вопросе.
s.nameиндексироваться?