К содержанию
ActionPulse

SQL-консоль

Прямой SQL по событиям своего проекта в ActionPulse — разрешённые запросы, доступные таблицы и поля, лимиты времени и результата, история запусков и рабочие примеры.

Кому
Аналитикам, знающим SQL
Проверено
На этой странице

Консоль нужна там, где готовых отчётов не хватает: своя нарезка по свойству события, разовая сверка перед релизом, проверка гипотезы, для которой не стоит собирать отчёт. Это ровно то же хранилище, из которого считаются воронки и удержание, — но запрос пишете вы.

Экран — Данные и сбор → Запросы к данным. Запуск: кнопка «Выполнить» или Cmd/Ctrl+Enter.

Что можно выполнять

Разрешён ровно один запрос на чтение. Точнее:

  • запрос начинается с SELECT или WITH;
  • это один statement — точка с запятой допускается только в самом конце;
  • JOIN, подзапросы, WITH-выражения, агрегатные функции и функции разбора JSON доступны обычным образом.

Отклоняется всё остальное — с кодом 422 и текстом, который называет конкретную причину:

Попытка Что вернётся
Два запроса через ; «multiple statements are not allowed»
Запрос, начинающийся не с SELECT/WITH «only SELECT/WITH queries are allowed»
Изменение данных или схемы отказ с указанием запрещённого слова
Обращение к внешнему источнику через табличную функцию отказ с указанием запрещённой функции
Своя секция настроек запроса отказ с указанием запрещённого слова
Незакрытый комментарий или кавычка «unterminated comment», «unterminated quoted value»

Проверка смотрит на слова вне строковых литералов и комментариев, а имена в кавычках разбирает как обычные слова — спрятать запрещённое слово в кавычках или обратных апострофах не получится.

Изоляция проекта

Область данных сужается до текущего проекта на стороне сервера, а не фильтром в вашем запросе. Практические следствия:

  • условие project_id = … писать не нужно: без него запрос уже видит только ваш проект;
  • добавить project_id другого проекта бессмысленно — строк не будет;
  • переключение проекта в кабинете меняет область данных консоли; черновик запроса при этом хранится отдельно для каждого проекта, так что переключение туда и обратно ничего не теряет.

Сообщения об ошибках базы наружу не проходят: вместо них приходит стабильный короткий отказ. Это сделано намеренно — текст исключения аналитической базы может содержать фрагменты запроса, имена объектов и детали устройства кластера.

Какие таблицы доступны

Панель схемы слева перечисляет всё, что можно читать; клик по имени вставляет его в позицию курсора. Доступны две таблицы.

events — по строке на событие:

Колонка Тип Что это
project_id UInt32 идентификатор проекта
event_id UUID идентификатор события
event_name LowCardinality(String) имя события
actor_id String итоговый субъект: user_id, если он известен, иначе anon_id
user_id String известный идентификатор пользователя
anon_id String анонимный идентификатор
session_id String сессия
event_time DateTime64(3) когда событие произошло
server_time DateTime64(3) когда событие пришло в ActionPulse
props String (JSON) свойства события строкой JSON
url String адрес страницы
referrer String реферер
utm_source, utm_medium, utm_campaign LowCardinality(String) UTM-метки
device_type, os, browser LowCardinality(String) производные признаки клиента
country LowCardinality(String) страна по IP-адресу

event_catalog — сводка по именам событий: project_id, event_name, last_seen (когда событие видели последний раз) и cnt (сколько его всего). Удобно, когда нужно быстро понять, что вообще приходит в проект.

Сырого IP-адреса и строки user-agent в схеме нет — они не хранятся, из них выводятся только country и признаки устройства. props — это строка JSON, поэтому значения достаются функциями работы с JSON, а не точкой.

Лимиты

Ограничение Значение
Строк в результате 100, 1000 или 10000 — выбирается в списке рядом с кнопкой запуска, по умолчанию 10000
Время выполнения 30 секунд
История запусков последние 50

Под таблицей результата видно, сколько строк вернулось, сколько заняло выполнение и сколько строк было прочитано. Последнее число — лучший индикатор тяжести запроса: если прочитано на порядки больше, чем вернулось, скорее всего не отсекается период.

Результат не кэшируется: каждый запуск идёт в базу заново.

Примеры

Топ событий за неделю — то же, что делает готовый шаблон «Топ событий за неделю»:

SELECT event_name, count() AS c
FROM events
WHERE event_time > now() - INTERVAL 7 DAY
GROUP BY event_name
ORDER BY c DESC
LIMIT 20

Активные субъекты по дням за месяц:

SELECT toDate(event_time) AS day, uniqExact(actor_id) AS actors
FROM events
WHERE event_time >= now() - INTERVAL 30 DAY
GROUP BY day
ORDER BY day

Разрез по свойству события — здесь видно, как читается props:

SELECT JSONExtractString(props, 'plan') AS plan, count() AS c
FROM events
WHERE event_name = 'subscription_started'
  AND event_time >= now() - INTERVAL 90 DAY
GROUP BY plan
ORDER BY c DESC

Полная лента одного человека (второй готовый шаблон, «События пользователя») — подставьте свой идентификатор вместо YOUR_USER_ID:

SELECT *
FROM events
WHERE actor_id = 'YOUR_USER_ID'
ORDER BY event_time DESC
LIMIT 100

Кроме двух базовых шаблонов панель схемы показывает раздел «По вашим определениям» — запросы, собранные под ваше событие полезной активности. Они появляются после того, как это событие указано в реестре событий; до тех пор там стоит ссылка «Настроить определение».

Сохранённый отчёт типа SQL открывается сразу в консоли с подставленным текстом. Список отчётов лежит в Мониторинг → Отчёты.

Если запрос не уложился в 30 секунд

Приходит 408 с кодом query_timeout, в интерфейсе — статус «Таймаут». В истории такой запуск сохраняется, так что текст запроса не теряется.

Что помогает, по убыванию эффекта:

  1. Сузить период. event_time — первое, что отсекает данные. Запрос без границы по времени читает всю доступную историю.
  2. Считать агрегат, а не выгружать строки. SELECT * без агрегации на большом периоде почти всегда упирается либо в таймаут, либо в лимит строк.
  3. Отфильтровать по event_name до группировки. Имя события — низкокардинальная колонка, фильтр по нему стоит дёшево.
  4. Не разбирать JSON по всей истории. Если нужен разрез по свойству, сначала сузьте выборку по имени события и периоду, и только потом извлекайте значение из props.
  5. Разбить на два запроса. Тяжёлый расчёт по кварталу часто быстрее собрать как три запроса по месяцу.

Если запрос нужен регулярно и упирается в лимиты — это сигнал, что задача переросла консоль: сохраните отчёт или посчитайте агрегат и выгрузите его, см. выгрузки.

История запусков

Вкладка «История» хранит последние 50 запусков проекта: время, автора, текст запроса, статус, длительность и число строк, плюс кнопку «Повторить».

Статусы: OK, Ошибка, Таймаут, Отклонён. В историю попадают все запуски, включая отклонённые проверкой и не уложившиеся в лимит времени, — это не только удобство, но и журнал: аналитик видит свои запуски, администратор и владелец — все запуски по проекту. Записи журнала хранятся 90 дней.

Что проверить

  • Результат ровно в 100, 1000 или 10000 строк — почти наверняка обрезан.
  • Считаете людей — берите uniqExact(actor_id), а не user_id: у неопознанных посетителей user_id пустой.
  • Считаете «когда произошло» — берите event_time. server_time показывает, когда событие дошло; у загруженной истории он равен моменту загрузки.
  • Нужен файл — кнопка «Экспорт CSV» на панели результата собирает его прямо в браузере из уже полученных строк. Это не серверная выгрузка: больше выбранного лимита строк она не отдаст.
  • Не видите раздела на своём сервере — в self-hosted-установке консоль появляется только после того, как администратор настроил для неё отдельное подключение к аналитической базе.