最佳做法和限制

使用 BatchJobService 时,请考虑以下准则。

提高吞吐量

  • 建议使用较少的较大作业,而不是许多较小的作业。

  • 按操作类型对上传的操作进行排序(必须在原子子批次中连续分组的相互依赖的操作除外)。例如,如果您的作业包含用于添加标准广告系列、广告组和广告组定位条件的操作,请在上传时对这些操作进行排序,以便所有广告系列操作排在最前面,其次是所有广告组操作,最后是所有广告组定位条件操作。

  • 对于同一类型的操作,按父资源对其进行分组可以提高性能。例如,如果您有一系列 AdGroupCriterionOperation 对象,按广告组对操作进行分组比混合影响不同广告组中广告组条件的操作更高效。

批量拆分的原子性

Google Ads API 会将提交的批量作业中的操作拆分为较小的子批次以进行处理。虽然标准子批处理在启用部分失败的情况下执行,但某些相互依赖的操作的子批处理会以单个事务的形式进行原子处理:

对于 AssetGroup 和效果最大化广告系列 Campaign 创建子批次(每个子批次最多包含 1,000 项操作;任何超出 999 项的子级 create 操作都会溢出到下一个非原子子批次):

如果原子子批处理失败,违规操作的 BatchJobResult.status 会包含底层验证错误,而该子批处理中的其余操作会回滚,并显示该子批处理的相应交易错误。检查共享相同 AdGroup、AssetGroup 或 Campaign ID 的相邻 BatchJobResult 条目,以确定根本原因错误。

如果未连续添加这些组中的相关操作,Google Ads API 会将它们拆分到不同的子批次中,导致修改操作未能满足最低素材资源要求或导致产品信息组树不完整。如需了解详情,请参阅在批量作业中使用产品信息组过滤条件和效果最大化广告系列批量处理。

逻辑分组

修改商品定位层次结构(效果最大化广告系列中的 AssetGroupListingGroupFilterOperation 或购物广告系列中的 AdGroupCriterionOperation)或创建新的 AssetGroup 或效果最大化广告系列 Campaign 时,请将定位到同一父资源(AssetGroup、AdGroup 或 Campaign)的所有操作连续分组。这样可以减少后端锁争用,并使相互依赖的树保持在一起。

数据一致性

由于系统会在每个原子子批次交易结束时验证产品信息组过滤树和效果最大化广告系列的素材资源要求,因此请避免在作业中或跨并发作业将对同一父资源的更新拆分到不连续的范围内。

避免并发问题

  • 为同一账号提交多个并发作业时,可降低作业同时对同一对象进行操作的可能性,同时保持较大的作业规模。许多状态为 RUNNING 的未完成作业尝试更改同一组对象,可能会导致类似死锁的情况,从而导致严重减速,甚至作业失败。

  • 请勿在同一作业中提交会更改同一对象的多个操作,因为结果可能无法预测。

以最佳方式检索结果

  • 请勿过于频繁地轮询作业状态,否则可能会遇到速率限制错误。

  • 调用 ListBatchJobResults 时,请将 page_size 保持未设置状态(或将其设置为最大值 1000),以最大限度地减少分页往返次数;只有当您的应用检查返回的资源字段(超出 resource_name)时,才将 response_content_type 设置为 MUTABLE_RESOURCE。

  • 结果顺序与上传顺序相同。

其他使用指南

限制

  • 每个 BatchJob 最多支持 100 万次操作。 在调用 AddBatchJobOperations 时超出此限制会返回 ResourceCountLimitExceededError.RESOURCE_LIMIT 错误(ErrorDetails.resource_count_details 中包含 ResourceLimitType.BATCH_JOB_OPERATIONS_PER_JOB)。

  • 每个账号最多可以同时有 100 个有效或待处理的作业。 如果在使用 MutateBatchJob 创建批量作业时超出此限制,系统会返回 ResourceCountLimitExceededError.RESOURCE_LIMIT 错误(ErrorDetails.resource_count_details 中包含 ResourceLimitType.BATCH_JOBS_PER_CUSTOMER)。

  • 系统会自动移除保留时长超过 7 天的待处理作业。

  • 每个 AddBatchJobOperationsRequest 的硬性限制为每个请求 10,000 次 mutate 操作。如果单个请求中的操作超过 10,000 个,系统会返回 BatchJobError.REQUEST_TOO_LARGE 错误。

  • 对于 ListBatchJobResultsRequest 中的 page_size 字段:

  • 每个 AddBatchJobOperationsRequest 的大小上限为 41,937,920 字节。如果超出此限制,您会收到 BatchJobError.REQUEST_TOO_LARGE 错误(如果在传输层被拒绝,则会收到 INTERNAL_ERROR 错误)。您可以在提交请求之前确定其序列化大小,并在请求过大时采取适当措施:

    Java

    
    static final int MAX_REQUEST_BYTES = 41_937_920;
    
    // ... (code to get the AddBatchJobOperationsRequest object)
    
    int sizeInBytes = request.getSerializedSize();
    

    C#

    
    const int MAX_REQUEST_BYTES = 41_937_920;
    
    // ... (code to get the AddBatchJobOperationsRequest object)
    
    int sizeInBytes = request.CalculateSize();
    

    PHP

    
    const MAX_REQUEST_BYTES = 41937920;
    
    // ... (code to get the AddBatchJobOperationsRequest object)
    
    $size_in_bytes = $request->byteSize();
    

    Python

    
    MAX_REQUEST_BYTES = 41_937_920
    
    # ... (code to get the AddBatchJobOperationsRequest object)
    
    size_in_bytes = type(request).pb(request).ByteSize()
    

    Ruby

    
    MAX_REQUEST_BYTES = 41_937_920
    
    # ... (code to get the AddBatchJobOperationsRequest object)
    
    size_in_bytes = request.to_proto.bytesize
    

    Perl

    
    use JSON::XS;
    use constant MAX_REQUEST_BYTES => 41937920;
    
    # ... (code to get the AddBatchJobOperationsRequest object)
    
    # The Perl client library uses REST/JSON; UTF-8 JSON byte length provides a
    # conservative upper-bound estimate of the serialized request size.
    my $json_encoder = JSON::XS->new->utf8->convert_blessed;
    my $size_in_bytes = length($json_encoder->encode($request));
    

单次突变操作的大小

虽然整个请求的大小上限为 41,937,920 字节,但批处理中单个 MutateOperation 的序列化大小上限为 10,484,504 字节(10 MiB 减去 1,256 字节)。如果超出此限制,则系统会返回 BatchJobError.REQUEST_TOO_LARGE 错误。请注意,虽然 BatchJobError.REQUEST_TOO_LARGE 的参考文档中引用了 10,484,504 字节的阈值,但当超出以下任一请求阈值(41,937,920 字节的总请求字节数、10,484,504 字节的单次操作字节数或每次调用 10,000 次操作)时,AddBatchJobOperations 都会返回此相同的错误代码,并且错误的 message 字段会指明违反了哪个限制。