Рекомендации по сегментации по внешним данным
Сегментация по внешним источникам данных — полезный инструмент, но при неправильной настройке она может стать причиной значительного замедления работы сегментов. Ниже собраны рекомендации, которые помогут избежать типичных проблем с производительностью.
Минимизация объёма данных
Внешние источники данных следует проектировать так, чтобы они возвращали как можно меньше данных. Чем меньше записей платформа должна обработать, тем быстрее будет рассчитан сегмент.
Основные правила:
- Возвращайте только колонку с идентификатором профиля, по которому происходит поиск. Дополнительные колонки не нужны и только увеличивают объём передаваемых данных.
- По возможности добавляйте фильтрацию прямо в запрос или в URL API. Например, если вам нужны только активные клиенты, добавьте
WHERE is_active = 1в SQL-запрос. Это уменьшит объём данных, которые платформа получит от внешней базы, и ускорит расчёт сегмента. - Для HTTP-запросов к API — внешний сервис должен возвращать только список идентификаторов, а не полные объекты с дополнительными полями.
- Для загружаемых файлов — файл должен содержать только нужную колонку с идентификаторами.
- Используйте параметр кэширования результата при создании SQL-запроса сегментации. Если данные меняются редко, кэширование значительно ускорит повторные расчёты сегмента.
Объединение условий в одном SQL-запросе
Когда вам нужно отфильтровать профили по нескольким условиям из одной внешней SQL-базы, лучше написать один запрос с объединёнными условиями, чем создавать несколько запросов и соединять и х в сегменте через «И».
Каждый отдельный запрос сегментации — это отдельное обращение к внешней базе. Чем больше запросов, тем дольше расчёт сегмента.
Пример. Представьте, что вам нужно выбрать клиентов, у которых есть активный договор и которые находятся в нужном регионе.
Неэффективный вариант — два отдельных запроса сегментации:
- Запрос «Договоры»:
SELECT id FROM contracts WHERE status = 'active' - Запрос «Регионы»:
SELECT id FROM customers WHERE region = 'Moscow'
Затем в сегменте эти два условия соединены через «И»:
В таблице данных (запрос "Договоры")
И
В таблице данных (запрос "Регионы")
Платформа выполнит два отдельных запроса к базе, получит два списка идентификаторов и пересечёт их внутри себя.
Эффективный вариант — один запрос сегментации с объединёнными условиями:
SELECT customers.id
FROM contracts
JOIN customers ON customers.id = contracts.customer_id
WHERE contracts.status = 'active' AND customers.region = 'Moscow'
В сегменте — одно условие:
В таблице данных (запрос "Договоры и регионы")
Платформа выполнит один запрос, и пересечение произойдёт на стороне базы данных — это быстрее.
Рекомендации:
- Если условия относятся к одной внешней базе — объединяйте их в один SQL-запрос с помощью JOIN, подзапросов или UNION.
- Если условия относятся к разным базам — объединить их в один запрос невозможно, и платформа выполнит их последовательно. В этом случае постарайтесь, чтобы каждый запрос возвращал как можно меньше записей.
- Используйте параметры запросов, чтобы сделать один универсальный запрос вместо не скольких похожих. Например, один запрос с параметром
{REGION}лучше, чем отдельные запросы для каждого региона. - Старайтесь, чтобы все запросы в сегменте обращались к одному полю профиля (например,
customer_id). Платформа может автоматически объединять запросы только если они привязаны к одному и тому же полю профиля и используют один коннектор.
Автоматическое объединение запросов
В платформе реализована оптимизация, которая позволяет объединять несколько запросов сегментации к одной внешней базе в единый SQL-запрос. Вместо того чтобы выполнять каждый запрос отдельно, выгружать результаты и пересекать их внутри платформы, платформа формирует один запрос с операциями INTERSECT (пересечение), UNION (объединение) или EXCEPT (исключение) — и выполняет его на стороне внешней базы.
Как это работает. Если в сегменте есть несколько условий «В табл ице данных», которые обращаются к одному коннектору и привязаны к одному и тому же полю профиля, платформа может объединить их:
В таблице данных (запрос "Договоры")
И
В таблице данных (запрос "Регионы")
Вместо двух отдельных запросов платформа сформирует один:
(SELECT id FROM query1) INTERSECT (SELECT id FROM query2)
Если одно из условий — «Не в таблице данных», платформа использует EXCEPT:
(SELECT id FROM query1) EXCEPT (SELECT id FROM query2)
Оптимизация включается администратором платформы (параметр SEGMENT_SQL_DATA_GROUP_OPTIMIZATION). Подробнее в документации администратора.
Ограничения:
- Объединяются только запросы одного коннектора и одного поля профиля.
- Если между запросами есть другие условия сегмента (не по внешней базе), объединение может не сработать. Например, конструкция вида
Запрос И (Запрос ИЛИ Условие)не может быть объединена, потому что не-запросное условие «разрывает» группу.
Раскрытие сегмента в сегменте
Если в условии сегмента используется другой сегмент (оператор «В сегменте»), платформа может раскрыть вложенный сегмент и включить его запросы к внешней базе в общую группировку для объединения.
Пример. Сегмент "VIP" содержит условие В таблице данных (запрос "VIP"). Родительский сегмент содержит:
В таблице данных (запрос "Активные клиенты")
И
В сегменте (сегмент "VIP")
Без раскрытия платформа выполнит запрос «Активные клиенты» отдельно, рассчитает сегмент "VIP" отдельно и пересечёт результаты.
С раскрытием платформа «увидит» запрос "VIP" из вложенного сегмента и объединит оба запроса в один SQL-запрос с INTERSECT.
Чтобы раскрытие сработало, должны выполняться все условия:
- Используется оператор «В сегменте». При использовании «Не в сегменте» стандартное раскрытие не сработает (см. Раскрытие «Не в сегменте»).
- Раскрытие работает только для динамических или обновляемых сегментов, так как они хранят условия сегментации. Для статических сегментов раскрытие не применяется — они содержат только готовый список профилей.
- Запросы вложенного и родительского сегмента обращаются к одному коннектору и привязаны к одному полю профиля.
- Операторы групп условий совпадают — если родитель использует «И», вложенный тоже должен использовать «И» (аналогично для «ИЛИ»).
Раскрытие сегмента в сегменте включается администратором платформы (параметры SEGMENT_SQL_SIS_EXPANSION, SEGMENT_SQL_SIS_MAX_DEPTH). Подробнее в документации администратора.
Раскрытие «Не в сегменте»
Для условий с оператором «Не в сегменте» реализована отдельная оптимизация. Она позволяет раскрыть вложенный сегмент и преобразовать отрицание: каждый оператор внутри вложенного сегмента заменяется на противоположный («равно» → «не равно», «содержит» → «не содержит», «больше» → «меньше или равно» и так далее), после чего запросы можно объединить с родительским сегментом.
Чтобы раскрытие сработало, должны выполняться все условия:
- Условие использует оператор «Не в сегменте».
- Вложенный сегмент не является статическим — динамический или обновляемый.
- Запросы вложенного и родительского сегмента обращаются к одному коннектору и привязаны к одному полю профиля.
- Все операторы во вложенном сегменте имеют пару-инверсию (например, «равно» ↔ «не равно», «содержит» ↔ «не содержит»). Если хотя бы один оператор не имеет пары — раскрытие не сработает.
Операторы без инверсии
Статус подписки: «Отписан», "Hardbounced", «Жалобщик», «Не валиден», «Приостановлен », «Не подтверждён», «Не существует».
Сценарии автоматизации: «хотя бы раз был», «никогда не был», «сейчас в сценарии», «сейчас не в сценарии», «вышел с ошибкой».
Формы: «заполнял», «не заполнял», «заполнял за выбранный период», «заполнял за последние [x] дней относительно текущей даты».
Даты: «тот же что и сегодня».
Активность в каналах: «Как минимум [n] раз», «Ни одного раза».
Кампании и ЛКГ: «не в ЛКГ».
Лояльность и заказы: «в диапазоне».
Связи: «Наличие / отсутствие прямой связи», «Наличие / отсутствие обратной связи».
Раскрытие «Не в сегменте» включается администратором платформы (параметры SEGMENT_SQL_SIS_NOT_EXPANSION, SEGMENT_GROUP_EXPANSION). Подробнее в документации администратора.
Условия с «НЕ» по внешним витринам
Условия сегментации по внешним витринам данных с оператором «НЕ» (например, «Не в таблице данных») приводят к сканированию всей базы профилей. Это происходит потому, что системе необходимо проверить каждый профиль на отсутствие во внешней выборке.
Рекомендации:
- Сведите количество условий с «НЕ» по внешним данным к минимуму.
- По возможности заменяйте отрицательные условия на позитивные. Например, вместо «Не в таблице данных» используйте «В таблице данных» с инвертированным запросом на стороне внешней базы.
- Если условие с «НЕ» необходимо, убедитесь, что внешняя витрина возвращает максимально компактный результат.
Подробнее об операторе «НЕ» в сегментах читайте в статье Рекомендации по работе с сегментами.