使用 GoogleAdsService 流式传输报告

如需检索 Google Ads API 实体和报告数据,请使用以下方法之一:

以下是这两种方法的主要区别:

GoogleAdsService.SearchStream GoogleAdsService.Search
适合用于生产代码 是 是
服务 GoogleAdsService GoogleAdsService
场景 提取对象和报告 提取对象和报告
响应 GoogleAdsRow 对象的 Stream GoogleAdsRow 个对象的页面
响应的字段 仅限查询中指定的那些 仅限查询中指定的那些
每日上限 基于访问权限级别的每日限额 基于访问权限级别的每日限额

虽然 Search 会发送多个分页请求来下载整个报告,但 SearchStream 会发送单个请求,并与 Google Ads API 建立持久的 gRPC 连接,无论报告大小如何。

对于 SearchStream,数据包会立即开始下载,每次下载 SearchGoogleAdsStreamResponse 个对象。您的代码可以在传入批次到达时对其进行迭代,而无需等待整个流完成。

无需往返网络时间即可请求 Search 响应的每个单独网页,因此与分页相比,SearchStream 可提供更高的性能,尤其是在处理大型报告时。

示例

此示例查看的是包含 100,000 行的报告。下表详细列出了这两种方法在请求和响应方面的区别:

SearchStream 搜索
页面大小 不适用 每页 10,000 行
API 请求数 1 个请求 10 个请求
API 响应数量 1 个连续数据流 10 个回答

性能因素

对于大多数使用场景,我们建议使用 SearchStream 而不是 Search,原因如下:

  • 单页报告(少于 10,000 行):这两种方法在性能方面没有显著差异。
  • 多页报告: SearchStream 通常速度更快,因为避免了多次网络往返,并且从磁盘缓存读取或写入的因素较小。
  • 内存效率:使用 SearchStream 处理大型报告时,请遍历流块并按行处理数据,而不是一次性将所有行缓冲到内存中,以避免内存不足 (OOM) 错误。
  • 连接弹性:由于 SearchStream 依赖于持久连接,因此长时间运行的流可能会因网络中断或截止时间超时而中断。配置适当的 RPC 超时,并针对暂时性流错误实现重试逻辑。

速率限制

这两种方法的日常操作限额均遵循 Google Cloud 项目的标准限额和访问权限级别。无论结果是使用 SearchStream 进行流式传输,还是使用 Search 通过多个缓存页面(使用 page_token)进行检索,单个逻辑报告查询都会计为一次操作,计入您的每日操作配额。不过,每个分页的 Search 请求仍会作为单独的 RPC 调用计入短期速率限制。

代码示例

以下代码示例演示了如何使用客户端库执行流式报告查询:

Java

private void runExample(GoogleAdsClient googleAdsClient, long customerId) {
  try (GoogleAdsServiceClient googleAdsServiceClient =
      googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
    String query = "SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id";
    // Constructs the SearchGoogleAdsStreamRequest.
    SearchGoogleAdsStreamRequest request =
        SearchGoogleAdsStreamRequest.newBuilder()
            .setCustomerId(Long.toString(customerId))
            .setQuery(query)
            .build();

    // Creates and issues a search Google Ads stream request that will retrieve all campaigns.
    ServerStream<SearchGoogleAdsStreamResponse> stream =
        googleAdsServiceClient.searchStreamCallable().call(request);

    // Iterates through and prints all of the results in the stream response.
    for (SearchGoogleAdsStreamResponse response : stream) {
      for (GoogleAdsRow googleAdsRow : response.getResultsList()) {
        System.out.printf(
            "Campaign with ID %d and name '%s' was found.%n",
            googleAdsRow.getCampaign().getId(), googleAdsRow.getCampaign().getName());
      }
    }
  }
}
      

C#

public void Run(GoogleAdsClient client, long customerId)
{
    // Get the GoogleAdsService.
    GoogleAdsServiceClient googleAdsService = client.GetService(
        Services.V25.GoogleAdsService);

    // Create a query that will retrieve all campaigns.
    string query = @"SELECT
                    campaign.id,
                    campaign.name,
                    campaign.network_settings.target_content_network
                FROM campaign
                ORDER BY campaign.id";

    try
    {
        // Issue a search request.
        googleAdsService.SearchStream(customerId.ToString(), query,
            delegate (SearchGoogleAdsStreamResponse resp)
            {
                foreach (GoogleAdsRow googleAdsRow in resp.Results)
                {
                    Console.WriteLine("Campaign with ID {0} and name '{1}' was found.",
                        googleAdsRow.Campaign.Id, googleAdsRow.Campaign.Name);
                }
            }
        );
    }
    catch (GoogleAdsException e)
    {
        Console.WriteLine("Failure:");
        Console.WriteLine($"Message: {e.Message}");
        Console.WriteLine($"Failure: {e.Failure}");
        Console.WriteLine($"Request ID: {e.RequestId}");
        throw;
    }
}
      

PHP

public static function runExample(GoogleAdsClient $googleAdsClient, int $customerId)
{
    $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
    // Creates a query that retrieves all campaigns.
    $query = 'SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id';
    // Issues a search stream request.
    /** @var GoogleAdsServerStreamDecorator $stream */
    $stream = $googleAdsServiceClient->searchStream(
        SearchGoogleAdsStreamRequest::build($customerId, $query)
    );

    // Iterates over all rows in all messages and prints the requested field values for
    // the campaign in each row.
    foreach ($stream->iterateAllElements() as $googleAdsRow) {
        /** @var GoogleAdsRow $googleAdsRow */
        printf(
            "Campaign with ID %d and name '%s' was found.%s",
            $googleAdsRow->getCampaign()->getId(),
            $googleAdsRow->getCampaign()->getName(),
            PHP_EOL
        );
    }
}
      

Python

def main(client: GoogleAdsClient, customer_id: str) -> None:
    ga_service: GoogleAdsServiceClient = client.get_service("GoogleAdsService")

    query: str = """
        SELECT
          campaign.id,
          campaign.name
        FROM campaign
        ORDER BY campaign.id"""

    # Issues a search request using streaming.
    stream: Iterator[SearchGoogleAdsStreamResponse] = ga_service.search_stream(
        customer_id=customer_id, query=query
    )

    for batch in stream:
        rows: List[GoogleAdsRow] = batch.results
        for row in rows:
            print(
                f"Campaign with ID {row.campaign.id} and name "
                f'"{row.campaign.name}" was found.'
            )
      

Ruby

def get_campaigns(customer_id)
  # GoogleAdsClient will read a config file from
  # ENV['HOME']/google_ads_config.rb when called without parameters
  client = Google::Ads::GoogleAds::GoogleAdsClient.new

  responses = client.service.google_ads.search_stream(
    customer_id: customer_id,
    query: 'SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id',
  )

  responses.each do |response|
    response.results.each do |row|
      puts "Campaign with ID #{row.campaign.id} and name '#{row.campaign.name}' was found."
    end
  end
end
      

Perl

sub get_campaigns {
  my ($api_client, $customer_id) = @_;

  # Create a search Google Ads stream request that will retrieve all campaigns.
  my $search_stream_request =
    Google::Ads::GoogleAds::V25::Services::GoogleAdsService::SearchGoogleAdsStreamRequest
    ->new({
      customerId => $customer_id,
      query      =>
        "SELECT campaign.id, campaign.name FROM campaign ORDER BY campaign.id"
    });

  # Get the GoogleAdsService.
  my $google_ads_service = $api_client->GoogleAdsService();

  my $search_stream_handler =
    Google::Ads::GoogleAds::Utils::SearchStreamHandler->new({
      service => $google_ads_service,
      request => $search_stream_request
    });

  # Issue a search request and process the stream response to print the requested
  # field values for the campaign in each row.
  $search_stream_handler->process_contents(
    sub {
      my $google_ads_row = shift;
      printf "Campaign with ID %d and name '%s' was found.\n",
        $google_ads_row->{campaign}{id}, $google_ads_row->{campaign}{name};
    });

  return 1;
}
      

curl