使用 GoogleAdsService 串流報表

如要擷取 Google Ads API 實體和報表資料,請使用下列其中一種方法:

這兩種方法的主要差異如下:

GoogleAdsService.SearchStream GoogleAdsService.Search
適合用於正式環境程式碼 是 是
服務 GoogleAdsService GoogleAdsService
情境 擷取物件和報表 擷取物件和報表
回應 GoogleAdsRow 物件的串流 GoogleAdsRow 物件的頁面
回應欄位 只有查詢中指定的資料 只有查詢中指定的資料
每日上限 根據存取層級設定每日上限 每日上限取決於存取層級

Search 會傳送多個分頁請求來下載完整報表,而 SearchStream 則會傳送單一請求,並與 Google Ads API 建立持續性 gRPC 連線,不受報表大小影響。

如果是 SearchStream,資料封包會立即開始以 SearchGoogleAdsStreamResponse 物件為單位批次下載。程式碼可以逐一處理傳入的批次,不必等待整個串流完成。

SearchStream 消除要求 Search 回應中每個個別頁面所需的來回網路時間,因此效能比分頁更佳,尤其是大型報表。

範例

本範例中的報表包含 100,000 列。下表列出這兩種方法在要求和回應方面的差異:

SearchStream 搜尋
頁面大小 不適用 每頁 10,000 列
API 要求數 1 項要求 10 項要求
API 回應數量 1 個連續串流 10 則回覆

成效因素

在大多數情況下,我們建議使用 SearchStream,而非 Search,原因如下:

  • 單頁報表 (10,000 列以下):兩種方法的效能沒有顯著差異。
  • 多頁報表: SearchStream 通常較快,因為可避免多次網路來回,且從磁碟快取讀取或寫入的影響較小。
  • 記憶體效率:使用 SearchStream 處理大型報表時,請逐一處理串流區塊,並在資料列送達時處理,而非一次將所有資料列緩衝至記憶體,以免發生記憶體不足 (OOM) 錯誤。
  • 連線穩定性:由於 SearchStream 依賴持續連線,因此網路中斷或截止時間逾時可能會導致長時間執行的串流中斷。設定適當的 RPC 超時,並針對暫時性串流錯誤實作重試邏輯。

頻率限制

這兩種方法的每日作業限制,都遵循 Google 雲端專案的標準限制和存取層級。無論結果是透過 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.'
            )
      

小茹

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