Как посчитать SRM в SQL
A/B-тест с планом 50/50, а в логах видим 53/47 при миллионе пользователей. Что описывает термин SRM (Sample Ratio Mismatch) применительно к этой ситуации?Содержание:
Зачем SRM
SRM (Sample Ratio Mismatch) — это когда фактическое распределение пользователей между вариантами A и B отличается от ожидаемого (например, от 50/50). Если есть SRM, тест сломан, а его результатам доверять нельзя. Проверка на SRM — обязательный этап перед анализом любого A/B-теста.
Формула
Chi-square test:
χ² = Σ ((observed - expected)² / expected)Если p-value < 0.001 (или 0.005), значит, обнаружен SRM.
Базовый расчёт
WITH observed AS (
SELECT
variant,
COUNT(DISTINCT user_id) AS n
FROM ab_test_assignments
WHERE test_id = 123
GROUP BY variant
),
total AS (
SELECT SUM(n) AS total_n FROM observed
)
SELECT
o.variant,
o.n AS observed,
t.total_n * 0.5 AS expected, -- 50/50 split
POW(o.n - t.total_n * 0.5, 2) / (t.total_n * 0.5) AS chi_sq_contribution
FROM observed o, total t
ORDER BY o.variant;Сложите все chi_sq_contributions. Сравните сумму с критическим значением chi-square (df=1 при двух вариантах): 10.83 соответствует p=0.001.
Когда SRM критична
При 50/50:
- N=10,000: 5050/4950 — нормально (chi² = 1.0, p ≈ 0.32)
- N=10,000: 5300/4700 — SRM (chi² = 36, p < 0.0001)
«Допустимый» перекос зависит от размера выборки. На большой выборке даже разница в 1% означает SRM.
Причины SRM
- Бот-трафик неравномерно распадается по вариантам.
- Баг в логике бакетирования — назначение в вариант смещено.
- Пропуски в трекинге — события теряются у одного из вариантов.
- Кеширование — старые пользователи застревают в старом бакете.
- Падение варианта — вариант B крашится, и его пользователей трекается меньше.
-- Drill: SRM by date
SELECT
DATE_TRUNC('day', assigned_at) AS day,
variant,
COUNT(*) AS users,
COUNT(*) FILTER (WHERE variant = 'A')::NUMERIC * 100 / COUNT(*) OVER (PARTITION BY DATE_TRUNC('day', assigned_at)) AS pct_a
FROM ab_test_assignments
WHERE test_id = 123
GROUP BY DATE_TRUNC('day', assigned_at), variant
ORDER BY day, variant;Если SRM появилась после какого-то дня, разбирайтесь с деплоем именно за эту дату.
SRM по сегментам
SRM в целом в норме, но в отдельном сегменте — сломан:
SELECT
u.country,
COUNT(*) FILTER (WHERE a.variant = 'A') AS a_users,
COUNT(*) FILTER (WHERE a.variant = 'B') AS b_users,
COUNT(*) FILTER (WHERE a.variant = 'A')::NUMERIC * 100 / COUNT(*) AS pct_a
FROM ab_test_assignments a
JOIN users u ON u.user_id = a.user_id
WHERE a.test_id = 123
GROUP BY u.country
HAVING ABS(COUNT(*) FILTER (WHERE a.variant = 'A')::NUMERIC * 100 / COUNT(*) - 50) > 3
ORDER BY 4;Частые ошибки
Ошибка 1. Игнорировать SRM. SRM — это проблема качества данных. Не доверяйте значимым результатам, пока не исключили SRM.
Ошибка 2. Слишком мягкий порог. α = 0.05 для SRM даёт много ложных тревог. Берите 0.001 или 0.005.
Ошибка 3. Проверять SRM только на старте. Перепроверяйте SRM регулярно — перекос нередко возникает уже в середине теста.
Ошибка 4. Не смотреть SRM по сегментам. В целом всё в норме, но в отдельном сегменте распределение перекошено. Перепроверьте стратификацию.
Ошибка 5. SRM в триггерных экспериментах. Логика триггера может срабатывать по-разному в разных вариантах. Проверяйте SRM ещё на пуле до экспозиции.
Связанные темы
- Как посчитать p-value в SQL
- Как посчитать sample size в SQL
- Как посчитать MDE в SQL
- Как посчитать statistical power в SQL
FAQ
Какой порог для SRM?
Берите p < 0.001 или 0.005. Порог держат строгим намеренно: SRM — критичная защитная проверка, и лучше лишний раз перепроверить тест, чем пропустить смещение.
SRM есть — что делать?
Остановите тест и разберитесь, где именно ломается — в распределении по вариантам или в трекинге событий. После того как нашли и починили причину, перезапускайте эксперимент заново.
Появился SRM один раз — перезапускать?
Да, перезапускать. Смещённым данным доверять нельзя, а цена починки почти всегда ниже цены неверного решения по продукту.
SRM в триггерных экспериментах?
Проверяйте SRM на пуле пользователей до экспозиции. Иногда сам триггер срабатывает смещённо и по-разному заводит людей в варианты — тогда причина именно в логике триггера, а не в самом сплите.
Есть ли инструменты с авто-проверкой SRM?
Да, Statsig, Optimizely и Eppo встроили проверку SRM из коробки. С 2024 года это фактически обязательная функция любой серьёзной A/B-платформы.