1.5Kпросмотров
1 июня 2025 г.
📷 ФотоScore: 1.6K
➡️Pattern matching(Префиксное сопоставление) Не все из указанных сегодня ф-ций подходят под определение классических Pattern Matching инструментов, но они отлично подходят для префиксного сопоставления из предыдущего поста, продолжение которого я обещал.😌 В процессе сбора информации, дабы быть максимально объективным, я наткнулся на статью в Хабре, которая отлично раскрывает сколько лошадок под капотом у каждого из рассматриваемых методов! (С применением индексов!).
Вкратце, добродушный Хабрчанин провёл research, а какой метод лучше работает для задачи префиксного сопоставления? Результат в приложенной к посту картинке! Вкратце суть картинки:
LIKE работает лучше на всех индексах Но я решил провести собственный research, и проверить, а как на моей задачи сработают данные методы без применения индексов? Кратко рассматриваемые варианты: 🔵LIKE
Классика жанра.
Быстрый, простой и эффективный при использовании шаблонов с левым якорем ('xxx%').
Отлично работает с индексами и без них. 🔵LEFT
Не совсем способ сопоставления, но часто используется для замены LIKE.
Позволяет брать фиксированную длину начала строки и сравнивать её с шаблоном:
LEFT(col, N) = 'xxx'
Работает быстро и стабильно, особенно при наличии btree-индекса по выражению.
Идеально, если нужно точное сравнение начала строки. 🔵~ / ~ (RegExp)
Регулярные выражения (с учётом / без учёта регистра).
Очень гибкие, поддерживают сложные шаблоны — но сильно проигрывают в скорости.
С индексами pg_trgm или spgist могут работать прилично, но всё равно медленнее LIKE. 🔵SIMILAR TO
Формально — SQL-стандарт. На деле — медленный костыль.
Под капотом переписывается в ~, но делает это неэффективно.
Плохо работает с индексами, сложно читается и ни в чём не выигрывает. 🔵STARTS WITH / ^@
Современный оператор (с PostgreSQL 11), аналог LIKE 'xxx%', но более наглядный.
Работает с spgist и (начиная с PostgreSQL 15) с btree COLLATE "C".
Без индексов — тоже быстрый. 🧐С теорией разобрались, но что на практике? 5 SIMILAR TO
Самый медленный. Постгрес переписывает это в регулярку, а потом ещё оборачивает в выражение. Потери на каждом этапе.
SELECT FROM sberbank_acc_operations
WHERE operation_description SIMILAR TO '%Заработная плата%|%Аванс%|%Отпускные%|%Расчет при увольнении%|%Командировочные%';
Planning Time: 4.504 ms
Execution Time: 21.851 ms 4 Регулярки ~
Гибкий инструмент, но требует сложных вычислений. Используется при поиске по шаблонам, примером может быть вычленение email-адресов/номеров телефонов из текстовых полей в БД. В рамках префиксного сопоставления место заслуженное.
SELECT FROM sberbank_acc_operations
WHERE operation_description ~ 'Заработная плата|Аванс|Отпускные|Расчет при увольнении|Командировочные';
Planning Time: 3.754 ms
Execution Time: 18.502 ms 🥉starts_with() или ^@
Начиная с PostgreSQL 11. Без индексов работает просто, но быстро — если шаблон чёткий. Немного проигрывает LEFT() в задаче префиксного сопоставления.
SELECT FROM sberbank_acc_operations
WHERE operation_description ^@ ANY(ARRAY['Заработная плата', 'Аванс', 'Отпускные', 'Расчет при увольнении', 'Командировочные']);
Planning Time: 2.533 ms
Execution Time: 8.133 ms 🥈LEFT()
Работает лучше регулярок, но требует нарезки каждой строки — не идеально, но на удивление отлично подошло в рамках моей задачи(отбор заработных транзакций).
SELECT FROM sberbank_acc_operations
WHERE LEFT(operation_description, 5) IN ('Зараб', 'Аванс', 'Отпус', 'Расче', 'Коман');
Planning Time: 0.263 ms
Execution Time: 2.563 ms 🥇LIKE с левым якорем ('xxx%')
Простой, понятный и эффективный. Даже без индексов — чемпион по скорости.
SELECT FROM sberbank_acc_operations
WHERE operation_description LIKE ANY( ARRAY[ 'Заработная плата%', 'Аванс%', 'Отпускные%', 'Расчет при увольнении%', 'Командировочные%' ]
);
Planning Time: 1.228 ms
Execution Ti