BigQuery ML против маркетплейсов: Как собрать свою рекомендательную систему для e-commerce в Казахстане за выходные
Суровая реальность: Выживание вне маркетплейсов
Давайте начистоту: делать классический e-commerce в Казахстане в 2026 году — это боль. С одной стороны вас давит желтый гигант с его рассрочками и бесплатной доставкой, с другой — фиолетовый монстр с миллионами ПВЗ. Если вы всё ещё пытаетесь конкурировать с ними в лоб, просто продавая те же чехлы для айфонов или утюги, у меня для вас плохие новости.
Ваш единственный шанс выжить — это нишевость, сервис и пользовательский опыт (UX). Но какой может быть UX, когда пользователь заходит на ваш сайт, видит простыню товаров из категории «Вам также может понравиться», где к зимним шинам предлагают купить летние кроссовки? Это фиаско, братан.
«Ну, нам нужна нейронка!» — скажет ваш продакт-менеджер. «Давайте наймем команду дата-саентистов, поднимем кластер Kubernetes, прикрутим Apache Spark, Kafka для стриминга и будем обучать графовые нейросети на GPU!» — радостно подхватит техлид, потирая руки в предвкушении освоения бюджета.
Спойлер: вы потратите полгода, $50k, а на выходе получите костыль, который будет падать при каждом деплое. А можно сделать иначе. Можно взять BigQuery ML, пару банок энергетика, выходные — и выкатить в прод рабочую рекомендательную систему, которая уделает 90% кастомных решений.
Что такое BigQuery ML и почему это чит-код?
BigQuery — это не просто колоночная база данных для аналитики, куда вы сливаете сырые логи из GA4. Это вычислительный монстр. А BigQuery ML (BQML) — это фича, которая позволяет обучать и выполнять модели машинного обучения прямо внутри хранилища данных, используя... обычный SQL!
Вам не нужно выгружать данные в Python, гонять их через Pandas, поднимать Jupyter Notebooks, страдать с зависимостями и деплоить Pickle-файлы на сервера. Данные остаются в BigQuery. Вычисления происходят в BigQuery. Вы просто пишете CREATE MODEL — и гугловская инфраструктура делает всю грязную работу за вас.
Задача: Рекомендация товаров на основе матричной факторизации (Collaborative Filtering)
Для e-commerce золотой стандарт стартовых рекомендаций — это коллаборативная фильтрация. Идея проста: если Арман и Серик купили одинаковые кроссовки и футболку, а Арман еще купил кепку, то Серику тоже стоит предложить эту кепку. Модель находит скрытые связи между пользователями и товарами на основе их истории взаимодействий (просмотры, добавления в корзину, покупки).
В BQML для этого используется алгоритм матричной факторизации (Matrix Factorization). Он берет матрицу «Пользователь — Товар — Оценка взаимодействия» и раскладывает ее на векторы (эмбеддинги). Звучит как матан, но для нас это просто пара строк кода.
Шаг 1: Подготовка данных (Фича-инжиниринг на коленке)
Главное правило ML: Garbage in, garbage out. Если скормить модели мусор, она выдаст мусор. Нам нужно собрать историю взаимодействий пользователей с товарами. Допустим, у нас есть сырые события из GA4 (в таблице events_*).
Мы не можем просто взять покупки — их слишком мало (разреженность данных). Нам нужны неявные сигналы (implicit feedback). Присвоим веса действиям:
- Просмотр товара (view_item) = 1 балл
- Добавление в корзину (add_to_cart) = 3 балла
- Покупка (purchase) = 10 баллов
-- Создаем витрину данных для обучения
CREATE OR REPLACE TABLE `ecommerce_ml.training_data` AS
WITH user_item_interactions AS (
SELECT
user_pseudo_id AS user_id,
(SELECT value.string_value FROM UNNEST(items) LIMIT 1) AS item_id,
event_name
FROM
`your-project.analytics_12345.events_*`
WHERE
event_name IN ('view_item', 'add_to_cart', 'purchase')
AND _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 90 DAY)) AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
)
SELECT
user_id,
item_id,
SUM(
CASE
WHEN event_name = 'view_item' THEN 1
WHEN event_name = 'add_to_cart' THEN 3
WHEN event_name = 'purchase' THEN 10
ELSE 0
END
) AS interaction_score
FROM
user_item_interactions
WHERE item_id IS NOT NULL
GROUP BY
user_id, item_id
HAVING interaction_score >= 1;Вот и весь дата-пайплайн. Никакого Airflow, Spark и долгих выгрузок. Данные уже в BQ.
Шаг 2: Обучение модели (Магия SQL)
Теперь самое сладкое. Учим нейронку (ну ладно, факторизацию матриц). Засекайте время:
-- Обучение модели матричной факторизации
CREATE OR REPLACE MODEL `ecommerce_ml.item_recommender`
OPTIONS(
model_type='matrix_factorization',
user_col='user_id',
item_col='item_id',
rating_col='interaction_score',
feedback_type='implicit', -- У нас неявные оценки (не 5 звезд, а клики)
l2_reg=0.1, -- Регуляризация, чтобы не переобучиться на ботах
num_factors=20 -- Размерность скрытых векторов (эмбеддингов)
) AS
SELECT
user_id,
item_id,
interaction_score
FROM
`ecommerce_ml.training_data`;Нажимаем Run. Уходим пить кофе. Через 10-15 минут модель готова. Google под капотом распараллелил вычисления на тысячах серверов, оптимизировал градиентный спуск и сохранил веса. Вы только что сэкономили месяц жизни дата-саентиста.
Шаг 3: Оценка качества (Метрики без булшита)
Модель обучилась, но как понять, что она не советует дичь? В BQML есть встроенная функция для эвалюации (оценки). Для неявного фидбека мы смотрим на метрику Mean Average Precision (MAP). Она показывает, насколько релевантными были товары в топе рекомендаций.
Зеленая зона PageSpeed Insights: 3 причины, почему оптимизация сайта жизненно важна для бизнеса
-- Оценка модели
SELECT * FROM ML.EVALUATE(MODEL `ecommerce_ml.item_recommender`);Если MAP выше 0.05 — для старта это уже пушка. Если меньше — надо крутить гиперпараметры (поиграться с l2_reg, добавить больше данных, фильтровать ботов-парсеров).
Шаг 4: Генерация предсказаний (Предикты в прод)
Теперь нам нужно получить топ-5 рекомендованных товаров для каждого пользователя. Делаем это одним запросом:
-- Получаем рекомендации
CREATE OR REPLACE TABLE `ecommerce_ml.user_recommendations` AS
SELECT
user_id,
ARRAY_AGG(STRUCT(item_id, predicted_interaction_score) ORDER BY predicted_interaction_score DESC LIMIT 5) AS recommended_items
FROM
ML.RECOMMEND(MODEL `ecommerce_ml.item_recommender`)
GROUP BY
user_id;У нас есть готовая таблица: user_id и массив из 5 лучших item_id для него.
Шаг 5: Архитектура отдачи (Highload для бедных, но умных)
Остался последний рывок. Как отдать эти рекомендации на фронтенд? Дергать BigQuery каждый раз, когда юзер заходит на главную страницу — это самоубийство бюджета (BQ берет деньги за просканированные терабайты) и дикие задержки (latency ~1-2 секунды, что для фронта смерть).
Поэтому мы делаем элегантно:
- Cloud Scheduler + Cloud Run (Job): Раз в сутки ночью запускаем скрипт, который выполняет SQL-запросы на переобучение модели и генерацию предиктов.
- Экспорт в Redis (или Cloud SQL): Скрипт забирает готовую таблицу
user_recommendationsиз BigQuery и пушит ее в in-memory базу (например, Redis Memorystore) или быстрый Cloud SQL (PostgreSQL). - Бэкенд (Node.js/Go): Фронтенд делает легкий GET-запрос
/api/recommendations?user_id=123. Бэкенд мгновенно (за 5 мс) забирает массив айдишников из Redis, джоинит с каталогом товаров (названия, цены, картинки) и отдает на фронт.
Сравнение затрат на разработку ML (Кастом против BQML)
Накопительные расходы ($) на инфраструктуру, зарплаты и поддержку в течение первого года.
Но постойте, а как же «Холодный старт»?
Любой душнила с Хабра спросит: «А что делать с новыми пользователями, у которых нет истории? Ваша матричная факторизация сломается!». Да, сломается. Для новых юзеров (холодный старт) мы не можем дать персонализированные рекомендации.
Поэтому в бэкенде мы пишем простой фолбэк (fallback):
// Псевдокод бэкенда на Node.js
async function getRecommendations(userId) {
// Пытаемся найти перс. рекомендации в Redis
let recs = await redis.get(`recs:${userId}`);
if (!recs) {
// Если юзер новый или инкогнито — отдаем глобальные хиты продаж
// Эту таблицу мы тоже заранее считаем в BQ и кладем в Redis!
recs = await redis.get('recs:global_top_sellers');
}
return expandItemsFromDatabase(recs);
}Всё. Никакой магии. Инженерия — это искусство находить простые костыли, которые работают в 99% случаев.
Цена вопроса: Сколько стоит этот киберпанк?
Давайте считать деньги. Мы же в Казахстане, тут за каждый тенге спросят.
- Хранение данных в BQ: Копейки (первые 10 ГБ бесплатно, дальше $0.02 за ГБ).
- Обучение модели (BQML): Вы платите за объем данных, обработанных при обучении. Если ваша витрина весит 1 ГБ, то обучение будет стоить примерно... бесплатно (в рамках бесплатного терабайта квоты BQ) или пару центов.
- Экспорт в Redis: Мелкий инстанс Redis (или бесплатный кластер от Upstash) обойдется от $0 до $15 в месяц.
Итого: Меньше $20 в месяц за полноценную рекомендательную систему, которая повысит конверсию на 5-15%.
Доля покупок по источнику рекомендаций (Ожидание)
Как распределяются покупки после внедрения BQML Collaborative Filtering.
Итог: Не усложняйте
Разработка — это не про то, чтобы использовать самые модные и сложные технологии. Это про то, как быстро доставить ценность бизнесу. Пока конкуренты пишут ТЗ на микросервисную архитектуру машинного обучения, вы за одни выходные собираете пайплайн на SQL, который уже в понедельник начинает приносить деньги.
BigQuery ML — это ультимативный швейцарский нож для data-инженеров и фулстеков. Да, он не выиграет Kaggle-соревнования. Да, он не умеет в сложные графовые архитектуры. Но для 95% бизнес-задач e-commerce (рекомендации, LTV, отток) его хватает с головой.
Хватит кормить маркетплейсы. Стройте свой UX. И да пребудет с вами высокий LTV и дешевый CAC!

Рустам Шарафутдинов
Эксперт в области архитектуры Google Cloud и Senior Full-Stack разработчик с более чем 15-летним опытом. Специализируется на отказоустойчивых архитектурах, оптимизации высоконагруженных проектов и интеграции AI (Vertex AI).