Добавление случайных данных

Внесение шума — это метод защиты конфиденциальности пользователя при выполнении запросов к базе данных. Он работает путём добавления случайного шума к агрегирующему предложению SELECT запроса. Этот шум защищает конфиденциальность пользователя, обеспечивая при этом достаточно точные результаты, устраняя необходимость в проверке различий и снижая требуемый порог агрегации для выходных данных. Большинство существующих запросов можно выполнять в режиме шума, но с некоторыми ограничениями .

Узнайте о преимуществах использования шумоподавления

Проверка различий не применяется: при выполнении запросов с добавлением шума Ads Data Hub не фильтрует строки по признаку сходства с предыдущими наборами результатов. Это означает, что вы по-прежнему можете получить целостное представление данных, сохраняя при этом конфиденциальность пользователей.

Упрощено устранение неполадок: строки опускаются только из-за требований агрегации, что упрощает устранение неполадок и адаптацию запросов.

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

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

Узнайте, как шум влияет на требования к конфиденциальности

Проверка различий: Вставка шума не использует существующие проверки различий в Ads Data Hub. При использовании вставки шума проверки различий отключаются.

Требование к агрегации: Вставка шума выводит данные о показах, представленные приблизительно 20 или более уникальными пользователями, и данные о кликах или конверсиях, представленные приблизительно 10 или более уникальными пользователями.

Статические проверки: нет воздействия.

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

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

Узнайте больше о проверках конфиденциальности .

Понять, как введение шума влияет на результаты

Ads Data Hub вводит шум, чтобы снизить риск раскрытия информации — риск того, что кто-то узнает информацию об отдельном пользователе. Это позволяет найти баланс между конфиденциальностью и полезностью.

Вставка шума в Ads Data Hub преобразует результаты запроса следующим образом:

  • Он ограничивает вклад пользователей, выпадающих из общего списка, в агрегированные результаты. Он суммирует вклад каждого пользователя в каждой агрегации, а затем ограничивает каждый вклад минимальными и максимальными границами ограничения.
  • Он объединяет фиксированные вклады каждого пользователя.
  • Он добавляет шум к каждому агрегированному результату — результату каждого вызова агрегирующей функции в каждой строке. Масштаб этого случайного шума пропорционален установленным границам.
  • Он вычисляет количество пользователей с шумом для каждой строки и исключает строки со слишком малым их числом. Это похоже на k-анонимность в режиме проверки различий, но из-за шума задания, работающие с одним и тем же набором данных, могут удалять разные строки. Кроме того, в режиме шума удаляется меньше строк, поскольку требования к агрегации ниже (примерно 20 против ровно 50).

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

О фиксации агрегации

В Ads Data Hub для вставки шума используется явное или неявное ограничение агрегации для ограничения влияния выбросов. Вы можете выбрать тип ограничения в зависимости от вашего варианта использования.

Неявное зажатие

Для использования неявного ограничения не требуется специальный синтаксис SQL, оно применяется по умолчанию. Неявные границы выводятся из самих данных и определяются для каждой агрегации. Если диапазон значений некоторых агрегаций шире, чем у других, неявное ограничение может выводить разные границы для разных агрегаций по мере необходимости. Обычно это приводит к снижению ошибок. Обратите внимание, что COUNT(DISTINCT user_id) автоматически использует явное ограничение с верхней границей 1 .

Явное зажатие

Явное ограничение ограничивает общий вклад каждого пользователя заданным диапазоном. Явные границы применяются единообразно ко всем агрегациям и должны быть литеральными значениями . Явное ограничение может дать лучшие результаты, когда границы общеизвестны. Например, ограничение возраста в диапазоне от 0 до 100 отражает общедоступную информацию, поскольку возраст большинства людей, как правило, находится в этом диапазоне.

Ads Data Hub предоставляет дополнительные агрегатные функции ADH.ANON для явного ограничения. Чтобы использовать явное ограничение, задайте границы для каждой поддерживаемой агрегатной функции, добавив целые числа, представляющие нижнюю и верхнюю границы. Например:

SELECT
campaign_name,
-- Set lower and upper bounds to 0 and 1, respectively
ADH.ANON_COUNT(*, contribution_bounds_per_group => (0,1))
FROM data
GROUP BY 1

Выполнить запрос с использованием инъекции шума

  1. Откройте отчет.
  2. Установите переключатель настроек конфиденциальности шума в положение « Использовать шум» .
  3. Выполнить запрос .
  4. Оцените воздействие дополнительного шума.
  5. Дополнительно: адаптируйте запрос , чтобы снизить влияние шума.

Оценить воздействие шума

После успешного завершения задания Ads Data Hub отображает надёжность результата в сводке конфиденциальности. Надёжность рассчитывается на основе процента ячеек в выходных данных, которые могут быть сильно затронуты шумом. Значение в таблице результатов считается затронутым, если масштаб добавленного шума превышает 5% от результата в ячейке.

Для наборов выходных данных, подвергшихся воздействию, в сводке по конфиденциальности перечислены десять столбцов с наибольшим уровнем шума (от наибольшего до наименьшего) и их вклад в уровень шума. Ниже представлена ​​разбивка по меткам уровня шума.

% затронутых результатов Цвет индикатора Влияние
<5% Зеленый Низкое воздействие
5%-15% Желтый Средний удар
15%-25% Апельсин Большое влияние
>25% Красный Очень сильное воздействие

Вы также можете просмотреть сводку по конфиденциальности для недавних заданий по отчётам на главной странице. Чтобы просмотреть сведения о конфиденциальности для конкретного задания, наведите указатель мыши на значок совета по конфиденциальности privacy_tip на карточке задания в разделе «Недавние действия» .

Адаптировать запросы

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

Ниже приведены общие рекомендации:

  • Расширьте диапазон дат.
  • Перепишите запрос, чтобы уменьшить детализацию данных, например, сгруппировав их по меньшему числу параметров или заменив COUNTIF на COUNT .
  • Удалите шумные столбцы.
  • Попробуйте использовать явное ограничение, когда можно выбрать разумные границы.

Поддерживаемые агрегатные функции

Следующие агрегатные функции поддерживаются с шумом:

  • SUM(...)
  • COUNT(*)
  • COUNT(...)
  • COUNTIF(...)
  • COUNT(DISTINCT user_id)
  • APPROX_COUNT_DISTINCT(user_id)
  • AVG(...)

Ключевое слово DISTINCT поддерживается только с функцией COUNT и только при использовании с прямой ссылкой на столбец user_id из таблицы Ads Data Hub или выражением, которое возвращает user_id или NULL , например COUNT(DISTINCT IF(..., user_id, NULL)) .

Обратите внимание, что эти ограничения применяются только к агрегациям с шумом, которые являются первым уровнем кросс-пользовательской агрегации. Агрегаты на уровне пользователя и агрегаты после добавления шума не имеют ограничений.

Дополнительные агрегатные функции

Помимо поддержки обычных агрегаторов, Ads Data Hub представляет дополнительные агрегатные функции ADH.ANON , поддерживающие явное ограничение. Эти агрегаторы имеют тот же синтаксис, что и дифференциально-приватные агрегатные функции BigQuery , однако для них не требуется предложение WITH DIFFERENTIAL_PRIVACY :

  • ADH.ANON_SUM( ..., [ contribution_bounds_per_group => (lower_bound, upper_bound) ] )

  • ADH.ANON_COUNT( *, [ contribution_bounds_per_group => (lower_bound, upper_bound) ] )

  • ADH.ANON_COUNT( ..., [ contribution_bounds_per_group => (lower_bound, upper_bound) ] )

  • ADH.ANON_AVG( ..., [ contribution_bounds_per_group => (lower_bound, upper_bound) ] )

  • ADH.ANON_PERCENTILE_CONT( ..., percentile, contribution_bounds_per_row => (lower_bound, upper_bound) )

Параметры ADH.ANON_SUM , ADH.ANON_COUNT и ADH.ANON_AVG :

  • contribution_bounds_per_group : Вклады каждого пользователя ограничиваются для каждого раздела, определяемого ключами GROUP BY . Верхняя и нижняя границы применяются к значениям для каждой группы после агрегирования значений для каждого пользователя.
  • lower_bound : числовой литерал, представляющий наименьшее значение, включаемое в агрегацию.
  • upper_bound : числовой литерал, представляющий наибольшее значение для включения в агрегацию.

Параметры ADH.ANON_PERCENTILE_CONT :

  • percentile : процентиль для вычисления, литерал в диапазоне [0, 1] .
  • contribution_bounds_per_row : Вклады каждого пользователя ограничиваются построчно (по каждой записи). Обратите внимание, что для процентиля требуются явные границы ограничения, поэтому он поддерживается только как дополнительная функция.
  • lower_bound : числовой литерал, представляющий наименьшее значение, включаемое в агрегацию.
  • upper_bound : числовой литерал, представляющий наибольшее значение для включения в агрегацию.

Вычислить МИН и МАКС

Функции MIN и MAX напрямую не поддерживаются в агрегациях шума, но часто существуют альтернативные методы вычисления этих результатов.

Если у вас есть MIN или MAX значение, которое можно использовать в качестве ключей группировки, например, дата события, вы можете сначала сгруппировать это значение, а затем вычислить MIN или MAX . Это вернет минимальное или максимальное значение, проходящее порог агрегации.

Пример:

WITH campaign_date_ranges AS (
  SELECT campaign_id, MIN(event_date) AS min_date, MAX(event_date) AS max_date
  FROM (
    # Aggregation thresholding will be applied here
    SELECT DISTINCT
      campaign_id,
      DATE(query_id.time_usec, @time_zone) AS event_date
    FROM adh.google_ads_impressions
  )
)
SELECT campaign_id, num_impressions, min_date, max_date
FROM (
  # Noise and aggregation thresholding will be applied here
  SELECT campaign_id, COUNT(*) AS num_impressions
  FROM adh.google_ads_impressions
)
JOIN campaign_date_ranges USING(campaign_id)

В качестве альтернативы, если у вас есть MIN или MAX детализированных значений с известными границами, вы можете использовать PERCENTILE_CONT с явными границами для получения приблизительного результата.

Пример:

SELECT
  campaign_id,
  COUNT(*) AS num_impressions,
  ADH.ANON_PERCENTILE_CONT(
    query_id.time_usec, 0,
    contribution_bounds_per_row => (@min_timestamp, @max_timestamp))
    AS min_timestamp,
  ADH.ANON_PERCENTILE_CONT(
    query_id.time_usec, 1,
    contribution_bounds_per_row => (@min_timestamp, @max_timestamp))
    AS max_timestamp
FROM adh.google_ads_impressions

О целочисленных результатах

Хотя Ads Data Hub автоматически добавляет шум для этих агрегатных функций, сигнатуры функций не меняются. Поскольку функции, такие как COUNT или SUM от INT64 , возвращают INT64 , любая десятичная часть зашумленного результата округляется. Обычно это пренебрежимо мало по сравнению с размером результата и шумом.

Если вам нужна точность десятичной дроби в результате, избегайте написания функций, возвращающих INT64 , например, используйте SUM с преобразованием ее входных данных в FLOAT64 .

Об отрицательных результатах

В принципе, шум с очень малыми значениями может привести к отрицательным числам, даже если это семантически невозможно для запроса. Для поддержания ожидаемого поведения все формы COUNT и COUNTIF автоматически ограничиваются нулем, поэтому они никогда не дают отрицательных результатов. Если вы хотите получить такое же поведение с другой функцией, например, SUM , вы можете ограничить результаты вручную, используя GREATEST(0, SUM(...)) .

Это изменение обычно незначительно, но оно вносит небольшое положительное смещение в общие результаты.

Публичные группы

С помощью предложения GROUP BY анонимизированные результаты запроса агрегируются по группам. Порог агрегации применяется для обеспечения достаточного количества пользователей в группе и защиты их данных. Процесс определения групп, которые могут быть освобождены, называется «выбором раздела».

Во многих случаях группы могут быть общедоступными. Например, группировка по версии браузера, дню недели или географическому региону не зависит от данных пользователя, если значения ключей группировки известны заранее. В этом случае выбор раздела можно опустить, поскольку наличие или отсутствие группы в результатах не даёт никакой новой информации о пользователях.

Ads Data Hub определяет запросы, подходящие для публичных групп, и не применяет к ним пороговое значение агрегации. Это означает, что ни одна выходная строка не отфильтровывается. Обратите внимание, что результаты, полученные для небольшого числа пользователей, могут быть сильно искажены шумом.

Чтобы запрос соответствовал публичным группам, он должен быть структурирован таким образом, чтобы все ключи группировки были известны заранее. Столбцы группировки должны удовлетворять следующим условиям:

  • Они берутся из общедоступной таблицы (таблицы или предложения SELECT без пользовательских данных Ads Data Hub).
  • Для обеспечения уникальности значений они применяют SELECT DISTINCT .
  • Они объединяются в запрос с помощью OUTER JOIN для всех отдельных столбцов.

Примеры запросов в публичных группах:

SELECT age_group_id, COUNT(*) FROM adh.google_ads_impressions
RIGHT OUTER JOIN (SELECT DISTINCT age_group_id FROM adh.age_group)
ON demographics.age_group = age_group_id
GROUP BY age_group_id
SELECT age_group_id, COUNT(*) FROM adh.google_ads_impressions
RIGHT OUTER JOIN (SELECT DISTINCT * FROM UNNEST([1, 2, 3]) AS age_group_id)
ON demographics.age_group = age_group_id
GROUP BY age_group_id

В первом примере защищённая adh.google_ads_impressions table объединяется с таблицей adh.age_group , которая не содержит данных о пользователях в столбце age_group_id . Тот же столбец age_group_id из общедоступной таблицы используется в предложении GROUP BY .

Аналогично, во втором примере защищённая таблица adh.google_ads_impressions объединяется с общедоступной таблицей, которая явно указана как UNNEST([1, 2, 3]) . Обратите внимание, что в обоих примерах ключ группировки age_group_id берётся из общедоступной таблицы.

Также можно указать несколько группирующих элементов, например:

SELECT campaign_id, COUNT(*) FROM adh.google_ads_impressions
RIGHT OUTER JOIN (SELECT DISTINCT campaign_id, customer_id FROM adh.google_ads_campaign)
USING (campaign_id, customer_id)
GROUP BY campaign_id, customer_id
SELECT p.campaign_id, p.browser, COUNT(*) FROM adh.google_ads_impressions AS i
RIGHT OUTER JOIN (
 SELECT DISTINCT * FROM UNNEST([1, 2]) AS campaign_id
 CROSS JOIN UNNEST(['Chrome', 'Other']) AS browser
) AS p
 ON i.campaign_id = p.campaign_id AND i.browser = p.browser
GROUP BY campaign_id, browser;

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

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


Поддерживаемые шаблоны запросов

Важно : большинство стандартных рекомендаций Ads Data Hub по-прежнему применимы к запросам, использующим шумовые данные. В частности, мы рекомендуем вам ознакомиться с рекомендациями по повторным запросам одних и тех же данных .

В этом разделе описываются шаблоны запросов, которые поддерживаются при выполнении запросов с использованием внедрения шума.

Агрегаты на уровне пользователя

Неограниченные агрегации на уровне пользователя поддерживаются так же, как и в режиме проверки различий. Шум добавляется только в агрегации, объединяющие данные нескольких пользователей. Агрегации, явно группирующие по user_id , или аналитические функции, разделяющие данные по user_id , не получают никакого шума, и разрешены любые функции. Агрегации на уровне пользователя, которые явно не группируют данные по user_id , например, GROUP BY impression_id , рассматриваются как кросс-пользовательские агрегации, поэтому шум добавляется.

Группировки по external_cookie недостаточно. Хотя external_cookie можно использовать для объединения таблиц *_match с таблицами, принадлежащими клиентам, любые агрегации для одного пользователя должны явно группироваться по столбцу user_id, а не только по столбцу external_cookie.

Пример агрегатной функции:

WITH user_paths AS (
  # Grouping by user_id, no noise needed, all functions allowed
  SELECT user_id, STRING_AGG(campaign_id, ">" ORDER BY query_id.time_usec) AS path
  FROM adh.google_ads_impressions
  GROUP BY 1
)
# Noise applied here to num_users
SELECT path, COUNT(*) AS num_users
FROM user_paths
GROUP BY 1;

Пример аналитической функции:

WITH events AS (
  # Partitioning by user_id, no noise needed, all functions allowed
  SELECT
    campaign_id,
    ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY query_id.time_usec) AS index
  FROM adh.google_ads_impressions
)
# Noise applied here to first_impressions
SELECT campaign_id, COUNT(*) AS first_impressions
FROM events
WHERE index = 1
GROUP BY 1;

Параллельные агрегаты

Каждая межпользовательская агрегация получает шум независимо. Вы можете запустить несколько таких агрегаций в одном операторе, объединяя результаты в одну таблицу с помощью JOIN или UNION .

Пример:

WITH result_1 AS (
  # Noise applied here to num_impressions
  SELECT campaign_id, COUNT(*) AS num_impressions
  FROM adh.google_ads_impressions
  GROUP BY 1
), result_2 AS (
  # Noise applied here to num_clicks
  SELECT campaign_id, COUNT(*) AS num_clicks
  FROM adh.google_ads_creative_conversions
  GROUP BY 1
)
SELECT * FROM result_1 JOIN result_2 USING(campaign_id)

Обратите внимание, что это поддерживается, но этого следует избегать в режиме проверки разностей. Эта практика не создаёт проблем с шумом, поскольку каждый параллельный агрегат подвергается шуму и фильтруется независимо.

Агрегированные данные, объединенные с неагрегированными данными

Поскольку Ads Data Hub поддерживает только аналитические окна, сепарируемые по user_id , распространённым решением является раздельное агрегирование этих результатов и их самообъединение перед повторным агрегированием. Такие запросы поддерживаются в режиме шума и часто работают лучше, чем в режиме проверки различий, благодаря более раннему выполнению требований конфиденциальности.

Пример:

WITH campaign_totals AS (
  # Noise applied here to campaign_imps
  SELECT campaign_id, COUNT(*) AS campaign_imps
  FROM adh.google_ads_impressions
  GROUP BY 1
)
# Noise applied here to imps
SELECT campaign_id, demographics, campaign_imps, COUNT(*) AS imps
FROM adh.google_ads_impressions JOIN campaign_totals USING(campaign_id)
GROUP BY 1,2,3

Режим шума препятствует повторному агрегированию совокупных результатов, таких как AVG(campaign_imps) .


Неподдерживаемые шаблоны запросов

В этом разделе описываются шаблоны запросов, которые не поддерживаются при выполнении запросов с использованием внедрения шума.

Запросы, включающие сегодня

Запросы в режиме шума не поддерживают запросы к данным за текущий день. (Это не рекомендуется делать в режиме проверки различий.) Текущая дата не может быть выбрана для запросов, использующих внедрение шума.

Повторные результаты

В режиме шума Ads Data Hub ограничивает частоту повторения одной и той же агрегации. При достижении этих ограничений запросы в режиме шума потеряют доступ к часто запрашиваемым датам в наборе данных. Ниже приведены примеры того, как это может произойти.

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

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

SELECT DATE(TIMESTAMP_MICROS(event.event_time)) AS date,
COUNT(*) AS cnt
FROM adh.cm_dt_clicks
GROUP BY 1

В этом случае вам следует выполнить запрос по непересекающимся сегментам дат.

Другой пример повторения возникает, когда данные в какой-то степени независимы от даты. Следующий запрос создаёт повторения при выполнении в перекрывающиеся даты, когда оба задания охватывают весь жизненный цикл кампании:

SELECT campaign_id, COUNT(*) AS cnt
FROM adh.google_ads_impressions
GROUP BY 1

В этом случае вам следует выполнить этот запрос только один раз, поскольку результат не изменится.

Повторение агрегации происходит, когда одна и та же агрегация повторяется несколько раз в запросе:

SELECT COUNT(*) AS cnt1, COUNT(*) AS cnt2
FROM table

В этом случае следует удалить один из повторов.

Обратите внимание, что даже если агрегации синтаксически различны, но вычисляют одно и то же значение, это будет считаться повторением. Другими словами, если значения condition1 и condition2 одинаковы для всех пользователей с каким-либо значением key , следующий запрос будет содержать повторение:

SELECT key, COUNTIF(condition1) AS cnt1, COUNTIF(condition2) AS cnt2
FROM table
GROUP BY key

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

Дублирование строк происходит при объединении таблицы Ads Data Hub с таблицей BigQuery таким образом, что каждая строка из таблицы Ads Data Hub соответствует нескольким строкам в таблице BigQuery. Например, следующий запрос создаст повторение, если в bq_table есть несколько строк с одинаковым идентификатором кампании:

SELECT r.campaign_id, COUNT(*) AS cnt
FROM adh_table
INNER JOIN bq_table ON l.campaign_id = r.campaign_id

В этом случае следует реструктурировать запрос так, чтобы bq_table имела только одну строку на каждое значение ключа соединения (в данном случае campaign_id ).

Обратите внимание, что извлечение массива из таблицы Ads Data Hub может привести к тому же эффекту, если у большинства пользователей одинаковые массивы значений:

SELECT in_market_id, COUNT(*)
FROM adh.dv360_youtube_impressions,
UNNEST(in_market) AS in_market_id
GROUP BY 1

Узнайте о других передовых методах выполнения запросов .

О окнах обратного просмотра

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

Например, если вы создаете отчет с показателями по дате, обновляемый ежедневно:

SELECT
  campaign_id,
  DATE(TIMESTAMP_MICROS(query_id.time_usec), @time_zone) AS event_date,
  COUNT(*) AS impressions
FROM adh.google_ads_impressions
GROUP BY 1,2

Не следует запускать это задание с большим диапазоном дат, так как это приведёт к пересчёту результатов за предыдущие дни. Вместо этого следует запускать каждое задание только для последнего дня, когда есть новые данные, а затем объединять результаты с результатами предыдущих заданий.

Если вам действительно необходимо обновить предыдущий результат (например, для учёта запоздалых данных), следует избегать пересчёта одного результата более 1-2 раз. В противном случае возможны ошибки из-за повторных попыток запроса.

Прямая реагрегация

Шум применяется к первому уровню кросс-пользовательской агрегации в запросе. Запросы с несколькими уровнями агрегации объединяют зашумленные результаты, поэтому итоговые агрегированные данные могут содержать гораздо больше шума. Такие запросы получают предупреждение при проверке:

WITH layer_1 AS (
  # Noise applied here to partial_result
  SELECT campaign_id, demographics, location, COUNT(*) AS partial_result
  FROM adh.google_ads_impressions
  GROUP BY 1,2,3
  HAVING partial_result > 5
)
# Reaggregation of partial_result with no user-level data, will be rejected
SELECT campaign_id, SUM(partial_result) AS final_result
FROM layer_1
GROUP BY 1

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

Если многоуровневая агрегация неизбежна, вы можете устранить предупреждение, экспортировав результаты непосредственно из первого уровня. Чтобы сделать это в рамках одного задания, не изменяя результаты скрипта, создайте временную таблицу (или таблицу, экспортированную в ваш проект BigQuery) с синтаксисом OPTIONS(privacy_checked_export=true) . Например:

CREATE TEMP TABLE layer_1 OPTIONS(privacy_checked_export=true) AS (
  # Noise applied here to partial_result
  SELECT campaign_id, demographics, location, COUNT(*) AS partial_result
  FROM adh.google_ads_impressions
  GROUP BY 1,2,3
  HAVING partial_result > 5
);
# Reaggregation of privacy checked data, no noise needed
SELECT campaign_id, SUM(partial_result) AS final_result
FROM layer_1
GROUP BY 1

Узнайте больше о временных таблицах .

Если первый уровень агрегации слишком детализирован для проверки конфиденциальности, рассмотрите возможность переписывания запроса с использованием агрегации на уровне пользователя . Если это невозможно, то запрос не поддерживается в режиме шума.

Неприсоединенные идентификаторы пользователей

Запросы в режиме шума не должны объединять данные отдельных пользователей в одну строку, за исключением случаев агрегации с шумом. Поэтому объединения неагрегированных данных Ads Data Hub должны явно объединяться по столбцу user_id .

Этот запрос явно не присоединяется к столбцу user_id , что приводит к предупреждению проверки:

SELECT 
FROM adh.google_ads_impressions
JOIN adh.google_ads_creative_conversions USING(impression_id)

Подобные объединения могут вести себя не так, как ожидается, поскольку будут совпадать только строки с одинаковым значением user_id . Это можно исправить, указав в предложении USING явное значение user_id , например, USING(impression_id, user_id) .

Обратите внимание, что это ограничение применяется только к соединениям таблиц Ads Data Hub (за исключением таблиц измерений). Оно не распространяется на таблицы, принадлежащие клиентам. Например, разрешено следующее:

SELECT 
FROM adh.google_ads_impressions
JOIN bigquery_project.dataset.table USING(any_column)

Ads Data Hub-BigQuery правые соединения

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

Оба этих запроса приводят к предупреждениям проверки, поскольку они допускают наличие несоответствующих строк с отсутствующими идентификаторами пользователей на стороне Ads Data Hub:

SELECT 
FROM adh.google_ads_impressions
RIGHT JOIN bigquery_project.dataset.table USING(column)
SELECT 
FROM bigquery_project.dataset.table
LEFT JOIN adh.google_ads_impressions USING(column)

Обратите внимание, что любое из этих объединений будет работать, если порядок таблиц обратен. Существует также исключение для таблиц RDID, которые объединяются непосредственно по device_id_md5 . Например, следующий запрос будет работать без предупреждений:

SELECT 
FROM bigquery_project.dataset.table
LEFT JOIN adh.google_ads_impressions_rdid USING(device_id_md5)

Сводка отфильтрованных строк

Спецификация сводки отфильтрованных строк не поддерживается в режиме шума. В шумовом режиме эта функция зачастую не нужна из-за низких скоростей фильтрации и отсутствия фильтрации при проверке разностей.

Если вы наблюдаете значительную фильтрацию данных в шумовом результате, увеличьте объём агрегированных данных. Вы можете выполнить параллельное агрегирование по всему набору данных, чтобы сравнить общую оценку, например:

SELECT campaign_name, COUNT(*)
FROM data
GROUP BY 1
UNION ALL
SELECT 'Total', COUNT(*)
FROM data
GROUP BY 1

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

Таблицы, созданные в кросс-режиме

Неэкспортированные таблицы в Ads Data Hub можно использовать только в том же режиме конфиденциальности, в котором они были созданы. Нельзя создать таблицу в обычном режиме агрегации и использовать её в режиме шума, и наоборот (если только эта таблица предварительно не экспортирована в BigQuery).

,

Внесение шума — это метод защиты конфиденциальности пользователя при выполнении запросов к базе данных. Он работает путём добавления случайного шума к агрегирующему предложению SELECT запроса. Этот шум защищает конфиденциальность пользователя, обеспечивая при этом достаточно точные результаты, устраняя необходимость в проверке различий и снижая требуемый порог агрегации для выходных данных. Большинство существующих запросов можно выполнять в режиме шума, но с некоторыми ограничениями .

Узнайте о преимуществах использования шумоподавления

Проверка различий не применяется: при выполнении запросов с добавлением шума Ads Data Hub не фильтрует строки по признаку сходства с предыдущими наборами результатов. Это означает, что вы по-прежнему можете получить целостное представление данных, сохраняя при этом конфиденциальность пользователей.

Упрощено устранение неполадок: строки опускаются только из-за требований агрегации, что упрощает устранение неполадок и адаптацию запросов.

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

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

Узнайте, как шум влияет на требования к конфиденциальности

Проверка различий: Вставка шума не использует существующие проверки различий в Ads Data Hub. При использовании вставки шума проверки различий отключаются.

Требование к агрегации: Вставка шума выводит данные о показах, представленные приблизительно 20 или более уникальными пользователями, и данные о кликах или конверсиях, представленные приблизительно 10 или более уникальными пользователями.

Статические проверки: нет воздействия.

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

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

Узнайте больше о проверках конфиденциальности .

Понять, как введение шума влияет на результаты

Ads Data Hub вводит шум, чтобы снизить риск раскрытия информации — риск того, что кто-то узнает информацию об отдельном пользователе. Это позволяет найти баланс между конфиденциальностью и полезностью.

Вставка шума в Ads Data Hub преобразует результаты запроса следующим образом:

  • Он ограничивает вклад пользователей, выпадающих из общего списка, в агрегированные результаты. Он суммирует вклад каждого пользователя в каждой агрегации, а затем ограничивает каждый вклад минимальными и максимальными границами ограничения.
  • Он объединяет фиксированные вклады каждого пользователя.
  • Он добавляет шум к каждому агрегированному результату — результату каждого вызова агрегирующей функции в каждой строке. Масштаб этого случайного шума пропорционален установленным границам.
  • Он вычисляет количество пользователей с шумом для каждой строки и исключает строки со слишком малым их числом. Это похоже на k-анонимность в режиме проверки различий, но из-за шума задания, работающие с одним и тем же набором данных, могут удалять разные строки. Кроме того, в режиме шума удаляется меньше строк, поскольку требования к агрегации ниже (примерно 20 против ровно 50).

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

О фиксации агрегации

В Ads Data Hub для вставки шума используется явное или неявное ограничение агрегации для ограничения влияния выбросов. Вы можете выбрать тип ограничения в зависимости от вашего варианта использования.

Неявное зажатие

Для использования неявного ограничения не требуется специальный синтаксис SQL, оно применяется по умолчанию. Неявные границы выводятся из самих данных и определяются для каждой агрегации. Если диапазон значений некоторых агрегаций шире, чем у других, неявное ограничение может выводить разные границы для разных агрегаций по мере необходимости. Обычно это приводит к снижению ошибок. Обратите внимание, что COUNT(DISTINCT user_id) автоматически использует явное ограничение с верхней границей 1 .

Явное зажатие

Явное ограничение ограничивает общий вклад каждого пользователя заданным диапазоном. Явные границы применяются единообразно ко всем агрегациям и должны быть литеральными значениями . Явное ограничение может дать лучшие результаты, когда границы общеизвестны. Например, ограничение возраста в диапазоне от 0 до 100 отражает общедоступную информацию, поскольку возраст большинства людей, как правило, находится в этом диапазоне.

Ads Data Hub предоставляет дополнительные агрегатные функции ADH.ANON для явного ограничения. Чтобы использовать явное ограничение, задайте границы для каждой поддерживаемой агрегатной функции, добавив целые числа, представляющие нижнюю и верхнюю границы. Например:

SELECT
campaign_name,
-- Set lower and upper bounds to 0 and 1, respectively
ADH.ANON_COUNT(*, contribution_bounds_per_group => (0,1))
FROM data
GROUP BY 1

Выполнить запрос с использованием инъекции шума

  1. Откройте отчет.
  2. Установите переключатель настроек конфиденциальности шума в положение « Использовать шум» .
  3. Выполнить запрос .
  4. Оцените воздействие дополнительного шума.
  5. Дополнительно: адаптируйте запрос , чтобы снизить влияние шума.

Оценить воздействие шума

После успешного завершения задания Ads Data Hub отображает надёжность результата в сводке конфиденциальности. Надёжность рассчитывается на основе процента ячеек в выходных данных, которые могут быть сильно затронуты шумом. Значение в таблице результатов считается затронутым, если масштаб добавленного шума превышает 5% от результата в ячейке.

Для наборов выходных данных, подвергшихся воздействию, в сводке по конфиденциальности перечислены десять столбцов с наибольшим уровнем шума (от наибольшего до наименьшего) и их вклад в уровень шума. Ниже представлена ​​разбивка по меткам уровня шума.

% затронутых результатов Цвет индикатора Влияние
<5% Зеленый Низкое воздействие
5%-15% Желтый Средний удар
15%-25% Апельсин Большое влияние
>25% Красный Очень сильное воздействие

Вы также можете просмотреть сводку по конфиденциальности для недавних заданий по отчётам на главной странице. Чтобы просмотреть сведения о конфиденциальности для конкретного задания, наведите указатель мыши на значок совета по конфиденциальности privacy_tip на карточке задания в разделе «Недавние действия» .

Адаптировать запросы

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

Ниже приведены общие рекомендации:

  • Расширьте диапазон дат.
  • Перепишите запрос, чтобы уменьшить детализацию данных, например, сгруппировав их по меньшему числу параметров или заменив COUNTIF на COUNT .
  • Удалите шумные столбцы.
  • Попробуйте использовать явное ограничение, когда можно выбрать разумные границы.

Поддерживаемые агрегатные функции

Следующие агрегатные функции поддерживаются с шумом:

  • SUM(...)
  • COUNT(*)
  • COUNT(...)
  • COUNTIF(...)
  • COUNT(DISTINCT user_id)
  • APPROX_COUNT_DISTINCT(user_id)
  • AVG(...)

Ключевое слово DISTINCT поддерживается только с функцией COUNT и только при использовании с прямой ссылкой на столбец user_id из таблицы Ads Data Hub или выражением, которое возвращает user_id или NULL , например COUNT(DISTINCT IF(..., user_id, NULL)) .

Обратите внимание, что эти ограничения применяются только к агрегациям с шумом, которые являются первым уровнем кросс-пользовательской агрегации. Агрегаты на уровне пользователя и агрегаты после добавления шума не имеют ограничений.

Дополнительные агрегатные функции

Помимо поддержки обычных агрегаторов, Ads Data Hub представляет дополнительные агрегатные функции ADH.ANON , поддерживающие явное ограничение. Эти агрегаторы имеют тот же синтаксис, что и дифференциально-приватные агрегатные функции BigQuery , однако для них не требуется предложение WITH DIFFERENTIAL_PRIVACY :

  • ADH.ANON_SUM( ..., [ contribution_bounds_per_group => (lower_bound, upper_bound) ] )

  • ADH.ANON_COUNT( *, [ contribution_bounds_per_group => (lower_bound, upper_bound) ] )

  • ADH.ANON_COUNT( ..., [ contribution_bounds_per_group => (lower_bound, upper_bound) ] )

  • ADH.ANON_AVG( ..., [ contribution_bounds_per_group => (lower_bound, upper_bound) ] )

  • ADH.ANON_PERCENTILE_CONT( ..., percentile, contribution_bounds_per_row => (lower_bound, upper_bound) )

Параметры ADH.ANON_SUM , ADH.ANON_COUNT и ADH.ANON_AVG :

  • contribution_bounds_per_group : Вклады каждого пользователя ограничиваются для каждого раздела, определяемого ключами GROUP BY . Верхняя и нижняя границы применяются к значениям для каждой группы после агрегирования значений для каждого пользователя.
  • lower_bound : числовой литерал, представляющий наименьшее значение, включаемое в агрегацию.
  • upper_bound : числовой литерал, представляющий наибольшее значение для включения в агрегацию.

Параметры ADH.ANON_PERCENTILE_CONT :

  • percentile : процентиль для вычисления, литерал в диапазоне [0, 1] .
  • contribution_bounds_per_row : Вклады каждого пользователя ограничиваются построчно (по каждой записи). Обратите внимание, что для процентиля требуются явные границы ограничения, поэтому он поддерживается только как дополнительная функция.
  • lower_bound : числовой литерал, представляющий наименьшее значение, включаемое в агрегацию.
  • upper_bound : числовой литерал, представляющий наибольшее значение для включения в агрегацию.

Вычислить МИН и МАКС

Функции MIN и MAX напрямую не поддерживаются в агрегациях шума, но часто существуют альтернативные методы вычисления этих результатов.

Если у вас есть MIN или MAX значение, которое можно использовать в качестве ключей группировки, например, дата события, вы можете сначала сгруппировать это значение, а затем вычислить MIN или MAX . Это вернет минимальное или максимальное значение, проходящее порог агрегации.

Пример:

WITH campaign_date_ranges AS (
  SELECT campaign_id, MIN(event_date) AS min_date, MAX(event_date) AS max_date
  FROM (
    # Aggregation thresholding will be applied here
    SELECT DISTINCT
      campaign_id,
      DATE(query_id.time_usec, @time_zone) AS event_date
    FROM adh.google_ads_impressions
  )
)
SELECT campaign_id, num_impressions, min_date, max_date
FROM (
  # Noise and aggregation thresholding will be applied here
  SELECT campaign_id, COUNT(*) AS num_impressions
  FROM adh.google_ads_impressions
)
JOIN campaign_date_ranges USING(campaign_id)

В качестве альтернативы, если у вас есть MIN или MAX детализированных значений с известными границами, вы можете использовать PERCENTILE_CONT с явными границами для получения приблизительного результата.

Пример:

SELECT
  campaign_id,
  COUNT(*) AS num_impressions,
  ADH.ANON_PERCENTILE_CONT(
    query_id.time_usec, 0,
    contribution_bounds_per_row => (@min_timestamp, @max_timestamp))
    AS min_timestamp,
  ADH.ANON_PERCENTILE_CONT(
    query_id.time_usec, 1,
    contribution_bounds_per_row => (@min_timestamp, @max_timestamp))
    AS max_timestamp
FROM adh.google_ads_impressions

О целочисленных результатах

Although Ads Data Hub will automatically inject noise for these aggregate functions, the function signatures don't change. Because functions like COUNT or SUM of INT64 return INT64 , any decimal part of the noised result is rounded. This is usually negligible relative to the size of the result and noise.

If you need the granularity of the decimal in your result, then avoid writing functions that return INT64 –for example, by using SUM with its input cast to FLOAT64 .

About negative results

In principle, noise with very small values can result in negative numbers, even when this should be semantically impossible for the query. To maintain expected behavior, all forms of COUNT and COUNTIF are automatically clamped at zero, so they never give negative results. If you want this same behavior with another function, such as SUM , then you can clamp results manually using GREATEST(0, SUM(...)) .

This change is usually negligible, but it does introduce a small positive bias to overall results.

Public groups

With a GROUP BY clause, the anonymized results of a query are aggregated over groups. Aggregation thresholding is applied to make sure that a sufficient number of users are present in the group so that individual user data is protected. The process of determining which groups can be released is called "partition selection".

In many cases groups may be public knowledge. For example, grouping by browser version, day of the week, or a geographical region does not depend on user data if the grouping key values are known in advance. In this instance, the partition selection can be omitted, since the presence or absence of a group in the output does not provide any new information about the users.

Ads Data Hub identifies queries eligible for public groups and does not apply aggregation thresholding to these queries. This means that no output rows are filtered out. Note that results computed from a small number of users can be heavily impacted by noise.

To be eligible for public groups, the query must be structured to ensure that all grouping keys are known in advance. The grouping columns must satisfy the following conditions:

  • They come from a public table (a table or SELECT clause with no Ads Data Hub user data).
  • They have SELECT DISTINCT applied to enforce unique values.
  • They are joined into the query with an OUTER JOIN on all of the individual columns.

Examples of public groups queries:

SELECT age_group_id, COUNT(*) FROM adh.google_ads_impressions
RIGHT OUTER JOIN (SELECT DISTINCT age_group_id FROM adh.age_group)
ON demographics.age_group = age_group_id
GROUP BY age_group_id
SELECT age_group_id, COUNT(*) FROM adh.google_ads_impressions
RIGHT OUTER JOIN (SELECT DISTINCT * FROM UNNEST([1, 2, 3]) AS age_group_id)
ON demographics.age_group = age_group_id
GROUP BY age_group_id

In the first example, the protected adh.google_ads_impressions table is joined with the adh.age_group table that does not contain user data on the age_group_id column. The same public table age_group_id column appears in the GROUP BY clause.

Similarly, in the second example the protected adh.google_ads_impressions table is joined with the public table, which is provided explicitly as UNNEST([1, 2, 3]) . Notice that in both examples, the grouping key age_group_id comes from the public table.

Multiple grouping items can be provided as well, for example:

SELECT campaign_id, COUNT(*) FROM adh.google_ads_impressions
RIGHT OUTER JOIN (SELECT DISTINCT campaign_id, customer_id FROM adh.google_ads_campaign)
USING (campaign_id, customer_id)
GROUP BY campaign_id, customer_id
SELECT p.campaign_id, p.browser, COUNT(*) FROM adh.google_ads_impressions AS i
RIGHT OUTER JOIN (
 SELECT DISTINCT * FROM UNNEST([1, 2]) AS campaign_id
 CROSS JOIN UNNEST(['Chrome', 'Other']) AS browser
) AS p
 ON i.campaign_id = p.campaign_id AND i.browser = p.browser
GROUP BY campaign_id, browser;

The absence of filtering in the public groups queries can be beneficial for recurrently run queries, since the output is always returned for the same fixed grouping keys' values. This can be particularly useful, for example, for building periodical dashboards.

A caveat: if a public table provides a very large number of grouping key values, then you may get many rows with little or no data, and these rows will all be reported as having high noise impact. In this case, you should consider explicitly providing a smaller list of keys with just the values you are interested in.


Supported query patterns

Important : Most of Ads Data Hub's standard best practices still apply to queries that use noise injection. In particular, we recommend that you review the guidance on repeatedly querying the same data .

This section describes query patterns that are supported when running queries using noise injection.

User-level aggregates

Unrestricted user-level aggregates are supported in the same way that they are in difference check mode. Noise is only injected in aggregations that combine data across multiple users. Aggregations that explicitly group by user_id , or analytic functions that partition by user_id , don't receive any noise and any function is allowed. User-level aggregations that don't explicitly group by user_id –for example, GROUP BY impression_id , are treated as cross-user aggregations, so noise is added.

Grouping by external_cookie is not enough. While external_cookie can be used to join *_match tables with customer-owned tables, any single-user aggregations should explicitly group by user_id column, not just the external_cookie column.

Aggregate function example:

WITH user_paths AS (
  # Grouping by user_id, no noise needed, all functions allowed
  SELECT user_id, STRING_AGG(campaign_id, ">" ORDER BY query_id.time_usec) AS path
  FROM adh.google_ads_impressions
  GROUP BY 1
)
# Noise applied here to num_users
SELECT path, COUNT(*) AS num_users
FROM user_paths
GROUP BY 1;

Analytic function example:

WITH events AS (
  # Partitioning by user_id, no noise needed, all functions allowed
  SELECT
    campaign_id,
    ROW_NUMBER() OVER(PARTITION BY user_id ORDER BY query_id.time_usec) AS index
  FROM adh.google_ads_impressions
)
# Noise applied here to first_impressions
SELECT campaign_id, COUNT(*) AS first_impressions
FROM events
WHERE index = 1
GROUP BY 1;

Parallel aggregates

Each cross-user aggregation receives noise independently. You can run multiple such aggregations in a single statement, combining results into one table using a JOIN or UNION .

Пример:

WITH result_1 AS (
  # Noise applied here to num_impressions
  SELECT campaign_id, COUNT(*) AS num_impressions
  FROM adh.google_ads_impressions
  GROUP BY 1
), result_2 AS (
  # Noise applied here to num_clicks
  SELECT campaign_id, COUNT(*) AS num_clicks
  FROM adh.google_ads_creative_conversions
  GROUP BY 1
)
SELECT * FROM result_1 JOIN result_2 USING(campaign_id)

Note that this would be supported but should be avoided in difference check mode. This practice is not a problem with noise, as each parallel aggregate is noised and filtered independently.

Aggregated data joined with unaggregated data

Since Ads Data Hub only supports analytic windows that partition by user_id , it is a common workaround to aggregate these results separately and self-join them before aggregating again. These queries are supported in noise mode, and often perform better than they would with in difference check mode due to privacy requirements being resolved earlier.

Пример:

WITH campaign_totals AS (
  # Noise applied here to campaign_imps
  SELECT campaign_id, COUNT(*) AS campaign_imps
  FROM adh.google_ads_impressions
  GROUP BY 1
)
# Noise applied here to imps
SELECT campaign_id, demographics, campaign_imps, COUNT(*) AS imps
FROM adh.google_ads_impressions JOIN campaign_totals USING(campaign_id)
GROUP BY 1,2,3

Noise mode discourages reaggregating aggregate results, such as AVG(campaign_imps) .


Unsupported query patterns

This section describes query patterns that are not supported when running queries using noise injection.

Today-inclusive queries

Noise mode queries don't support querying the current day's data. (This is discouraged in difference check mode.) The current date is not selectable for queries that use noise injection.

Repeated results

In noise mode, Ads Data Hub limits how often you can repeat the same aggregation. If you reach these limits, your noise mode queries will lose access to frequently queried dates in the dataset. The following are examples of how this can occur.

Query repetition happens when the same query is run multiple times with the same parameters or highly similar parameters, such as overlapping date ranges. You can avoid this by using data that is already exported to your BigQuery project.

Note that if two jobs are querying overlapping date ranges, they might produce repetitions if performing the same computation on the same users. For example, the following query, executed on overlapping date ranges, creates repetitions because it partitions by date:

SELECT DATE(TIMESTAMP_MICROS(event.event_time)) AS date,
COUNT(*) AS cnt
FROM adh.cm_dt_clicks
GROUP BY 1

In this case, you should run the query on disjoint date segments.

Another example of a repetition happens when data is somewhat date independent. The following query produces repetitions when executed on overlapping dates, where both jobs cover the entire lifetime of a campaign:

SELECT campaign_id, COUNT(*) AS cnt
FROM adh.google_ads_impressions
GROUP BY 1

In this case, you should run this query only once since the result doesn't change.

Aggregation repetition happens when the same aggregation is repeated multiple times within a query:

SELECT COUNT(*) AS cnt1, COUNT(*) AS cnt2
FROM table

In this case, you should remove one of the repetitions.

Note that even if the aggregations are syntactically different but compute the same value, it would count as a repetition. In other words, if the values of condition1 and condition2 are the same for all users with some value of key , the following query would have a repetition:

SELECT key, COUNTIF(condition1) AS cnt1, COUNTIF(condition2) AS cnt2
FROM table
GROUP BY key

If you have conditions that are very similar for some groups of users, you might consider rewriting the query to have only one COUNT .

Row duplication happens when an Ads Data Hub table is joined with a BigQuery table in a way that each row from the Ads Data Hub table matches multiple rows in the BigQuery table. For example, the following query produces a repetition if there are multiple rows with the same campaign ID in bq_table :

SELECT r.campaign_id, COUNT(*) AS cnt
FROM adh_table
INNER JOIN bq_table ON l.campaign_id = r.campaign_id

In this case, you should restructure the query so that bq_table would have only one row per join key value ( campaign_id , in this case).

Note that unnesting an array from the Ads Data Hub table could produce the same effect if most users have the same arrays of values:

SELECT in_market_id, COUNT(*)
FROM adh.dv360_youtube_impressions,
UNNEST(in_market) AS in_market_id
GROUP BY 1

Learn about other query best practices .

About Lookback Windows

Some query patterns generate reports over a large timeframe, periodically regenerating to include new results. These queries may need adjustments to work in noise mode because if they recompute previous results, they will be blocked. Instead, each job should only generate new results, then new results can be combined with results from previous jobs for a full report.

For example, if you are creating a report of metrics by date, refreshed daily:

SELECT
  campaign_id,
  DATE(TIMESTAMP_MICROS(query_id.time_usec), @time_zone) AS event_date,
  COUNT(*) AS impressions
FROM adh.google_ads_impressions
GROUP BY 1,2

You shouldn't run this with a large date range as this will recompute results of previous days. Instead, you should run each job only the latest day, which has new data, then combine with results from previous jobs.

If you do need to refresh a previous result (for example to account for late arriving data), then you should avoid recomputing any single result more than 1 or 2 times. Otherwise, you may get errors due to repeated query attempts.

Direct reaggregation

Noise is applied to the first layer of cross-user aggregation in the query. Queries with multiple layers of aggregation will combine noisy results, so final aggregates may have much higher noise. These queries receive a warning on validation:

WITH layer_1 AS (
  # Noise applied here to partial_result
  SELECT campaign_id, demographics, location, COUNT(*) AS partial_result
  FROM adh.google_ads_impressions
  GROUP BY 1,2,3
  HAVING partial_result > 5
)
# Reaggregation of partial_result with no user-level data, will be rejected
SELECT campaign_id, SUM(partial_result) AS final_result
FROM layer_1
GROUP BY 1

To get the best results from noise, compute all cross-user operations within a single aggregation. For example, take a SUM of events rather than a SUM of intermediate counts.

If multi-layer aggregation is unavoidable, you can resolve the warning by exporting results directly from the first layer instead. To do this within a single job without changing script results, create a temp table (or a table exported to your BigQuery project) with the OPTIONS(privacy_checked_export=true) syntax. For example:

CREATE TEMP TABLE layer_1 OPTIONS(privacy_checked_export=true) AS (
  # Noise applied here to partial_result
  SELECT campaign_id, demographics, location, COUNT(*) AS partial_result
  FROM adh.google_ads_impressions
  GROUP BY 1,2,3
  HAVING partial_result > 5
);
# Reaggregation of privacy checked data, no noise needed
SELECT campaign_id, SUM(partial_result) AS final_result
FROM layer_1
GROUP BY 1

Learn more about temp tables .

If the first layer of aggregation is too granular for privacy checks, consider rewriting the query with user-level aggregates . If this is not possible, then this query is not supported in noise mode.

Unjoined user IDs

Queries in noise mode must not combine data from separate users into a single row, except when performing an aggregation with noise. As a result, joins of unaggregated Ads Data Hub data should explicitly join on the user_id column.

This query does not explicitly join on the user_id column, which results in a validation warning:

SELECT 
FROM adh.google_ads_impressions
JOIN adh.google_ads_creative_conversions USING(impression_id)

Joins like this may not behave as expected because only rows with the same user_id value will match. This can be fixed by adjusting the USING clause to explicitly include user_id – for example, USING(impression_id, user_id) .

Note that this limitation applies only to joins between Ads Data Hub tables (with the exception of dimension tables). It does not apply to customer-owned tables. For example, the following is allowed:

SELECT 
FROM adh.google_ads_impressions
JOIN bigquery_project.dataset.table USING(any_column)

Ads Data Hub-BigQuery right joins

Outer joins with customer-owned data can lead to rows with missing user identifiers, which prevents noise from working well.

Both of these queries result in validation warnings because they allow for unmatched rows with missing user identifiers on the Ads Data Hub side:

SELECT 
FROM adh.google_ads_impressions
RIGHT JOIN bigquery_project.dataset.table USING(column)
SELECT 
FROM bigquery_project.dataset.table
LEFT JOIN adh.google_ads_impressions USING(column)

Note that either join would work if the order of the tables was reversed. There is also an exception for RDID tables that join directly on device_id_md5 . For example, the following query will work with no warnings:

SELECT 
FROM bigquery_project.dataset.table
LEFT JOIN adh.google_ads_impressions_rdid USING(device_id_md5)

Filtered Row Summary

The filtered row summary spec is not supported in noise mode. This feature is most often unnecessary with noise due to lower filtering rates and the lack of filtering from difference checks.

If you observe significant data filtering in a noise result, then increase the aggregated data. You may perform a parallel aggregation over the full dataset to compare an estimate of the total, for example:

SELECT campaign_name, COUNT(*)
FROM data
GROUP BY 1
UNION ALL
SELECT 'Total', COUNT(*)
FROM data
GROUP BY 1

Note that the total count is independently noised and total values may not add up, but the total count is often more accurate than taking the sum of noised rows.

Cross-mode created tables

Unexported tables in Ads Data Hub can only be used with the same privacy mode where they were created. You can't create a table in normal aggregation mode and use it in noise mode, or the other way around (unless that table is exported to BigQuery first).