细分字段

本页面介绍了如何查看和控制与 MongoDB 兼容的 Firestore 中碎片化字段的使用情况。此功能在 Firestore 企业版中提供。

写入文档时,Firestore 可能会确定应以碎片化格式存储特定字段。细化字段通过仅读取所需字段(而非完整文档)来优化查询性能。

可从切分字段中受益的查询

当有以下查询形状时,对碎片化字段的读取会应用于这些查询形状:

  • 聚合查询:仅需访问部分字段即可进行聚合操作的查询。例如:

    db.customers.aggregate(
      [
        { $match: { "account_balance" : { $lt : 0 } } },
        { $count: "total" }
      ]
    );
    

    或使用分组依据:

    db.customers.aggregate([
      { $match: { "account_balance" : { $lt : 0 } } },
      {
        $group: {
          _id: "$market_segment",
          avg_balance: { $avg: "$account_balance" }
        }
      }
    ]);
    
  • 投影查询:仅返回特定字段子集的查询。例如:

    db.customers.find({}, { family_name: 1, given_name: 1, _id: 0 });
    
  • 过滤查询:过滤 Firestore 查询引擎确定使用碎片化字段进行文档过滤有益的查询。例如:

    db.customers.find({ given_name: "Alice" });
    

查看粉碎字段的使用情况

您可以使用查询解释功能来检查查询是否使用了碎片化字段。查询计划中的 TableScan 节点包含一个 Storage 部分,其中包含以下指标:

  • 扫描形状
    • shredded_fields_only:查询仅从碎片化字段读取数据。
    • shredded_fields_backjoin:查询从碎片化字段读取数据,并与原始文档联接以获取其他字段。
  • 使用的碎片化字段:作为碎片化字段读取的属性名称列表。
  • 重新检查次数:重新检查的计数器映射。重新检查是指在扫描碎片化字段时,回退到从原始完整文档中读取。如果文档中的字段值超过 8 KiB,即超过了碎片化字段存储空间的大小,则可能会发生这种情况。

输出示例

...
└── • TableScan
        source: **/customers
        order: UNDEFINED
        row range: (-∞..+∞)
        filter: $lt($account_balance_1, 0)
        output bindings: {$account_balance_1=account_balance, $market_segment_1=market_segment}
        variables: [$account_balance_1, $market_segment_1]

        Execution:
         records returned: 1,374
         latency: 26.58 ms
         post-filtered rows: 13,626
         records scanned: 15,000
         data bytes read: 23.73 MiB (24,887,141 B)

        Storage:
         scan shape: shredded_fields_only
         shredded fields used: [account_balance, market_segment]

控制碎片化字段的使用

默认情况下,与 MongoDB 兼容的 Firestore 会使用碎片化字段(如果可用)。您可以使用查询注释中的 tableScanMethod 选项来控制此行为。

tableScanMethod 的支持值:

  • shreddedFieldsEnabled(默认):使用碎片化字段(如有)。
  • shreddedFieldsDisabled:不会使用碎片化字段。
  • forceShreddedFields:如果无法通过扫描碎片化字段来满足表扫描,则使查询失败。

查找命令

使用 .comment() 方法为 find 命令指定选项:

db.customers.find(
  { account_balance: 0.0 }
).comment(
  {
    firestoreOptions: {
      tableScanMethod: "shreddedFieldsDisabled"
    }
  }
);

汇总命令

aggregate 命令的 options 参数中使用 comment 选项:

db.customers.aggregate(
  [
    { $match: { "account_balance" : { $lt : 0 } } },
    { $count: "total" }
  ],
  {
    comment: {
      firestoreOptions: {
        tableScanMethod: "shreddedFieldsDisabled"
      }
    }
  }
);

查询性能警告

如果检测到分片字段使用效率低下,与 MongoDB 兼容的 Firestore 可能会在查询解释结果中发出性能警告。例如:

  • 选择性较低的查询:如果查询扫描碎片化字段以进行过滤,但过滤掉的文档很少,导致扫描效率低下。

  • 高重新检查查询:如果查询经常回退到完整文档读取,可能会影响性能。您可以使用 $bsonSize 等运算符来识别触发重新检查的大值。

在这些情况下,请考虑使用查询选项停用碎片化字段读取。

限制

Firestore 仅尝试粉碎顶级字段。它还限制了每个集合可粉碎的字段数量。