高效管理数据

许多 Google Ads 应用的核心功能是检索账号数据,以用于数据分析、客户查询和政策合规性检查等使用情形。在提取数据时,您应优化使用情况,以免 Google 服务器过载,或面临速率限制的风险。如需了解详情,请参阅有关速率限制和保持最新联系电子邮件地址的指南。

了解 Google 的报告资源用量政策

为确保服务器的稳定性,Google Ads API 会限制消耗过多 API 资源的 GoogleAdsService.SearchGoogleAdsService.SearchStream 查询模式。如果特定查询模式受到限制,其他服务、方法和查询模式将继续正常运行,不受影响。对于受限的请求,系统会抛出以下错误:

错误代码
QuotaError.EXCESSIVE_SHORT_TERM_QUERY_RESOURCE_CONSUMPTIONQuotaError.EXCESSIVE_LONG_TERM_QUERY_RESOURCE_CONSUMPTION,具体取决于高资源使用率的持续时间。

为了帮助您识别和监控费用高昂的报告,我们还会针对各个报告返回费用指标。

方法 费用字段
GoogleAdsService.Search SearchGoogleAdsResponse.query_resource_consumption
GoogleAdsService.SearchStream SearchGoogleAdsStreamResponse.query_resource_consumption

这些字段返回的费用指标取决于多种因素,例如

  • 账号规模
  • 您在报告中提取的视图和列
  • Google Ads API 服务器的负载。

为了帮助您跟踪高成本查询,我们将发布有关服务器上各种查询模式的资源消耗的初始汇总统计信息。我们会定期发布更新后的数字,帮助您微调查询。

时间窗口 平均值 (p50)。 P70(中高) P95(非常高)
短期(5 分钟) 6000 30000 1800000
长期(24 小时)。 16000 90000 8400000

例如,假设您运行的查询模式如下所示,每个报告消耗 600 个单位的资源。

SELECT campaign.id, campaign.name, metrics.cost_micros FROM campaign WHERE
    segments.date = "YYYY-MM-DD"

您可以修改查询,将不同的值替换为 segments.date 过滤条件,从而针对多个客户账号在多个单独的日期运行此查询。下表显示了您可以在给定的时间窗口内运行的报告数量,以便资源用量符合各种资源用量分段。

时间窗口 平均值 较高 很高
短期(5 分钟) 10 50 3000
长期(24 小时)。 26 150 14000

在 5 分钟内运行此查询模式 10 次属于平均使用量,而在 5 分钟内运行 3, 000 次报告则属于非常高的使用量。

您可以采取多种策略来优化报告的资源消耗。本指南的其余部分将介绍其中一些策略。

缓存数据

您应在本地数据库中缓存从 API 服务器提取的实体详细信息,而不是每次需要数据时都调用服务器,尤其是对于经常访问或很少更改的实体。尽可能使用 change-eventchange-status 来检测自上次同步结果以来哪些对象发生了更改。

优化报告运行频率

Google Ads 已发布有关数据新鲜度和数据更新频率的指南。您应根据此指南确定提取报告的频率。

如果您需要定期更新账号,建议您将此类账号的数量限制为少量,例如仅限前 20 个 Google Ads 账号。其余数据可以较低的频率更新,例如每天一次或两次。

优化报告的大小

您的应用应提取大批量数据,而不是运行大量小型报告。影响此选择的一个因素是账号限制

例如,请考虑以下代码,该代码用于提取特定广告组的统计信息并更新统计信息数据库表:

  List<long> adGroupIds = FetchAdGroupIdsFromLocalDatabase();

  foreach (long adGroupId in adGroupIds)
  {
    string query = "SELECT ad_group.id, ad_group.name, metrics.clicks, " +
        "metrics.cost_micros, metrics.impressions, segments.date FROM " +
        "ad_group WHERE segments.date DURING LAST_7_DAYS AND " +
        "ad_group.id = ${adGroupId}";
    List<GoogleAdsRow> rows = RunGoogleAdsReport(customerId, query);
    InsertRowsIntoStatsTable(adGroupId, rows);
  }

此代码在小型测试账号上运行良好。不过,Google Ads 支持每个广告系列最多包含 20,000 个广告组,每个账号最多包含 10,000 个广告系列。因此,如果此代码针对的是大型 Google Ads 账号,则可能会使 Google Ads API 服务器过载,从而导致速率限制和节流。

更好的方法是运行单个报告,并在本地处理该报告。下面展示了一种使用内存中映射的方法。

  Hashset<long> adGroupIds = FetchAdGroupIdsFromLocalDatabase();

  string query = "SELECT ad_group.id, ad_group.name, metrics.clicks, " +
      "metrics.cost_micros, metrics.impressions, segments.date FROM " +
      "ad_group WHERE segments.date DURING LAST_7_DAYS";
  List<GoogleAdsRow> rows = RunGoogleAdsReport(customer_id, query);

  var memoryMap = new Dictionary<long, List<GoogleAdsRow>>();
  for each (GoogleAdsRow row in rows)
  {
    var adGroupId = row.AdGroup.Id;

    if (adGroupIds.Contains(adGroupId))
    {
      CheckAndAddRowIntoMemoryMap(row, adGroupId, memoryMap);
    }
  }
  foreach (long adGroupId in memoryMap.Keys())
  {
    InsertRowsIntoStatsTable(adGroupId, rows);
  }

这样可以减少因运行的报告数量较少而给 Google Ads API 服务器带来的负载。

如果您发现报告过大,无法存储在内存中,还可以通过添加如下所示的 LIMIT 子句将查询分解为较小的组:

SELECT
  ad_group.id,
  ad_group.name,
  metrics.clicks,
  metrics.cost_micros,
  metrics.impressions,
  segments.date
FROM ad_group
WHERE segments.date DURING LAST_7_DAYS
  AND ad_group.id IN (id1, id2, ...)
LIMIT 100000

标签是另一种对实体进行分组并减少报告查询次数的方式。如需了解详情,请参阅标签指南

优化提取的内容

运行报告时,您应注意查询中包含的列。请看以下示例,该示例计划每小时运行一次:

SELECT
  customer.id,
  customer.currency_code,
  campaign.id,
  campaign.name,
  ad_group.id,
  ad_group.name,
  ad_group_criterion.keyword.match_type,
  ad_group_criterion.keyword.text,
  ad_group_criterion.criterion_id,
  ad_group_criterion.quality_info.creative_quality_score,
  ad_group_criterion.system_serving_status,
  ad_group_criterion.negative,
  ad_group_criterion.quality_info.quality_score,
  ad_group_criterion.quality_info.search_predicted_ctr,
  ad_group_criterion.quality_info.post_click_quality_score,
  metrics.historical_landing_page_quality_score,
  metrics.search_click_share,
  metrics.historical_creative_quality_score,
  metrics.clicks,
  metrics.impressions
FROM keyword_view
WHERE segments.date DURING LAST_7_DAYS

可能每小时都会变化的列只有 metrics.clicksmetrics.impressions。所有其他列的更新频率都很低,甚至根本不更新,因此每小时提取一次这些列非常低效。您可以将这些值存储在本地数据库中,并运行更改事件更改状态报告,以便每天下载一次或两次更改。

在某些情况下,您可以通过应用适当的过滤条件来减少下载的行数。

清理未使用的账号

如果您的应用管理第三方客户账号,那么您在开发应用时需要考虑客户流失问题。您应定期清理流程和数据存储区,以移除不再使用您应用的客户的账号。清理不常用的 Google Ads 账号时,请谨记以下指导:

  • 撤消客户授予您的应用管理其账号的授权。
  • 停止向客户的 Google Ads 账号发出 API 调用。这尤其适用于旨在无需用户干预即可运行的离线作业,例如 cron 作业和数据流水线。
  • 如果客户撤消了授权,您的应用应妥善处理这种情况,避免向 Google 的 API 服务器发送无效的 API 调用。
  • 如果客户已取消其 Google Ads 账号,您应检测到此情况,并避免向 Google 的 API 服务器发送无效的 API 调用。
  • 在适当的时间段过后,从本地数据库中删除您从客户的 Google Ads 账号下载的数据。