データを効率的に管理する

多くの Google 広告アプリケーションのコア機能は、データ分析、顧客からの問い合わせ、ポリシー準拠チェックなどのユースケースで使用するアカウント データを取得することです。 データを取得する際は、Google サーバーに過負荷をかけたり、レート制限のリスクを負ったりしないように、使用量を最適化する必要があります。詳しくは、 レート制限最新の連絡先メールアドレスの維持に関するガイドをご覧ください。

レポートに関する Google のリソース利用ポリシーについて

サーバーの安定性を確保するため、Google 広告 API は、 GoogleAdsService.SearchGoogleAdsService.SearchStreamクエリ パターンを抑制します。これらのパターンは、API リソースを過剰に 消費します。特定のクエリ パターンが抑制されても、他のサービス、メソッド、クエリパターンは影響を受けずに動作します。抑制されたリクエストに対しては、次のエラーがスローされます。

エラーコード
QuotaError.EXCESSIVE_SHORT_TERM_QUERY_RESOURCE_CONSUMPTION または QuotaError.EXCESSIVE_LONG_TERM_QUERY_RESOURCE_CONSUMPTION は、リソース使用率が高い期間に応じて異なります。

これらのエラーが発生した場合は、QuotaError.EXCESSIVE_SHORT_TERM_QUERY_RESOURCE_CONSUMPTION で失敗したリクエストを再試行する前に 5 分間、QuotaError.EXCESSIVE_LONG_TERM_QUERY_RESOURCE_CONSUMPTION で失敗したリクエストを再試行する前に 30 分間待ってください。

高コストのレポートを特定してモニタリングできるように、個々のレポートの費用指標も返されます。

メソッド 費用フィールド
GoogleAdsService.Search SearchGoogleAdsResponse.query_resource_consumption
GoogleAdsService.SearchStream SearchGoogleAdsStreamResponse.query_resource_consumption

これらのフィールドから返される費用指標は、次のようなさまざまな要因によって異なります。

  • アカウントのサイズ
  • レポートで取得するビューと列
  • Google 広告 API サーバーの負荷。

高コストのクエリを追跡できるように、Google はサーバーで確認されたさまざまなクエリ パターンのリソース消費量に関する最初の集計統計情報を公開しています。クエリを微調整できるように、定期的に更新された数値を公開します。

期間 平均(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 サーバーから取得したエンティティの詳細をローカル データベースにキャッシュに保存する必要があります。特に、頻繁にアクセスされるエンティティや、変更頻度の低いエンティティの場合は、キャッシュに保存することをおすすめします。可能な場合は、変更イベント変更ステータスを使用して、前回の結果の同期以降に変更されたオブジェクトを検出します。

レポートの実行頻度を最適化する

Google 広告は、データの更新速度とデータの更新頻度に関するガイドラインを公開しています。このガイダンスを使用して、レポートの取得頻度を決定する必要があります。

アカウントを定期的に更新する必要がある場合は、そのようなアカウントの数を少ないセット(たとえば、上位 20 個の Google 広告アカウントのみ)に制限することをおすすめします。残りのアカウントは、1 日に 1 回または 2 回など、低い頻度で更新できます。

レポートのサイズを最適化する

アプリケーションでは、多数の小さなレポートを実行するのではなく、大量のデータをバッチで取得する必要があります。この選択に影響する要因は、アカウント の上限です。

たとえば、特定の広告グループの統計情報を取得して統計情報データベース テーブルを更新する次のコードについて考えてみます。

  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 広告では、キャンペーンごとに最大 20,000 個の広告グループ、アカウントごとに 10,000 個のキャンペーンがサポートされています。そのため、このコードを大規模な Google 広告アカウントに対して実行すると、Google Ads API サーバーに過負荷がかかり、レート制限と抑制が発生する可能性があります。

より良い方法は、1 つのレポートを実行してローカルで処理することです。インメモリ マップを使用した方法を次に示します。

  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 広告 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

ラベルは、エンティティをグループ化してレポート クエリの数を減らすもう 1 つの方法です。詳しくは、ラベルに関するガイドをご覧ください。

取得する内容を最適化する

レポートを実行する際は、クエリに含める列に注意する必要があります。1 時間ごとに実行するようにスケジュールされている次の例について考えてみます。

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

1 時間ごとに変更される可能性のある列は、metrics.clicksmetrics.impressions のみです。他の列は頻繁に更新されないため、1 時間ごとに取得するのは非常に非効率的です。これらの 値をローカルデータベースに保存し、変更イベントまたは 変更ステータスレポートを実行して、1 日に 1 回または 2 回変更をダウンロードできます。

適切なフィルタを適用することで、ダウンロードする行数を減らすことができる場合があります。

使用されていないアカウントをクリーンアップする

アプリケーションでサードパーティの顧客アカウントを管理している場合は、顧客の離反を考慮してアプリケーションを開発する必要があります。プロセスとデータストアを定期的にクリーンアップして、アプリケーションを使用しなくなった顧客のアカウントを削除する必要があります。使用されていない Google 広告アカウントをクリーンアップする際は、次のガイダンスに留意してください。

  • 顧客がアプリケーションに付与した、アカウントを管理する権限を取り消します。
  • 顧客の Google 広告アカウントへの API 呼び出しを停止します。これは、ユーザーの操作なしで実行するように設計された cron ジョブやデータ パイプラインなどのオフライン ジョブに特に当てはまります。
  • 顧客が権限を取り消した場合、アプリケーションは状況を適切に処理し、Google の API サーバーに無効な API 呼び出しを送信しないようにする必要があります。
  • 顧客が Google 広告アカウントをキャンセルした場合は、それを検出し 、Google の API サーバーに無効な API 呼び出しを送信しないようにする必要があります。
  • 適切な期間が経過したら、顧客の Google 広告アカウントからダウンロードしたデータをローカル データベースから削除します。