Оптимизация LIKE типа "% sample_string %"

460 views
Skip to first unread message

Stepan Semiokhin

unread,
Sep 20, 2016, 11:40:43 AM9/20/16
to ClickHouse
Добрый день!

Столкнулся с такой проблемой: сильно тянет вниз выполнение всего запроса условие
STR LIKE "% sample_string %"
Понимаю, что вряд ли в такой задаче в принципе есть способ обойти фул скан, но, мало ли, вы что посоветуете, кроме изменения структуры таким образом, чтобы было "sample_string%" или "%sample_string"... Может какие магические ходы есть?

man...@gmail.com

unread,
Sep 20, 2016, 4:21:38 PM9/20/16
to ClickHouse
Сам по себе поиск подстроки в строке довольно сильно оптимизирован, но не использует индекс (за исключением варианта с фиксированным префиксом).
То есть, для сканирования данных, он должен выполняться быстро. Но полнотекстового индекса нет.

Магические ходы возможны, но их трудно применять.
Например: есть ли возможность из каждого значения STR выделить всего лишь один токен (подстроку, либо какое-нибудь ещё преобразование) так, что поиск искомых данных будет уже не LIKE, а всего лишь сравнением этого токена на равенство?
Ещё пример: существует ли возможность выделить столбец, который будет намного меньше чем STR, но всё ещё подходить для поиска? Тогда искать в этом столбце будет намного проще не смотря на full scan.

Stepan Semiokhin

unread,
Sep 22, 2016, 4:23:13 AM9/22/16
to ClickHouse
Спасибо!

Нашел решение своей проблемы и хотел бы обсудить с вами, чтобы понимать, почему так, у меня был запрос типа:
SELECT *
FROM table
WHERE
date = 'some_date'
AND some_field LIKE '%abc%'  # тот самый тяжелый лайк
AND (куча различных условий)
LIMIT 10

Я получил максимальное производительность (скорость увеличилась в 5 раз, нагрузка упала в сотню), переписав его следующим образом:

SELECT *
FROM
(
SELECT *
FROM table
WHERE
date = 'some_date'
AND some_field LIKE '%abc%'  # тот самый тяжелый лайк
)
WHERE (куча различных условий)
LIMIT 10

Откуда такой прирост? Я понимаю, что тут более "явно" обрезаны данные для *кучи различных условий*, но чтоб так это повлияло...

вторник, 20 сентября 2016 г., 23:21:38 UTC+3 пользователь man...@gmail.com написал:

Stepan Semiokhin

unread,
Sep 22, 2016, 5:04:34 AM9/22/16
to ClickHouse
А еще я в принципе экспериментировал и в зависимости от того, какие условия я вношу/выношу из подзапроса время выполнения меняется прямо таки на порядок, от 0.17 сек. до 5.5 сек.+
Просто немного похоже на хак и хочется как-то детерминировать эту ситуацию, чтобы не подбирать каждый раз экспериментально формат запроса с лайком)

четверг, 22 сентября 2016 г., 11:23:13 UTC+3 пользователь Stepan Semiokhin написал:

man...@gmail.com

unread,
Sep 22, 2016, 10:20:47 PM9/22/16
to ClickHouse
Это возможно, если все условия кроме LIKE вычислительно сложные, а сам LIKE достаточно селективен. К тому же, все остальные условия не влияют на использование индекса.

Тогда получается так:
В первом варианте запроса, все условия в WHERE вычисляются, затем производится фильтрация строк.
Во втором варианте запроса, вычисляется LIKE, производится фильтрация строк по его результату, затем по гораздо меньшему количеству строк, вычисляются все остальные условия, и снова производится фильтрация.

Это доказывает, что вопреки изначальному предположению, как раз LIKE работает максимально быстро.

Для того, чтобы такую оптимизацию запроса можно было бы делать автоматически, понадобилось бы собирать статистику селективности условий и сложности их вычисления.
Reply all
Reply to author
Forward
0 new messages