文档菜单
文档首页
/
MongoDB 手册
/ / / / /

加密集合

本页内容

  • 概述
  • 元数据集合
  • 等值和范围查询影响
  • 等值可查询字段的写入成本
  • 插入操作
  • 更新操作
  • 删除操作
  • 等值可查询字段的存储成本
  • 最佳实践
  • 元数据集合压缩
  • 安排元数据压缩
  • 运行元数据压缩

字段级加密伴随着性能和存储成本。您选择的每个要加密的字段

  • 都会增加插入和更新操作的写入。

  • 需要额外的存储空间,因为MongoDB维护一个加密字段的索引以改进查询性能。

本节总结了加密集合的存储和写入影响,并解释了如何压缩加密集合索引以最小化这些成本。如果您想加密字段并为其配置查询,请参阅加密字段和启用查询.

可查询加密引入了使用随机加密加密文档中的敏感字段的能力,同时仍然能够查询加密字段。

使用可查询加密,给定的明文字值始终加密为不同的密文,同时仍然可查询。为了启用此功能,可查询加密使用三种数据结构

  • 两个元数据集合

  • 加密集合中每个文档中的一个字段,称为__safeContent__

警告

这些数据结构不得修改或删除,否则查询结果将不正确。

当您创建一个加密集合时,MongoDB会创建两个元数据集合

  • enxcol_.<collectionName>.esc,称为 ESC

  • enxcol_.<collectionName>.ecoc,称为 ECOC

示例

如果您创建一个名为“patients”的集合,MongoDB会创建以下元数据集合

  • enxcol_.patients.esc

  • enxcol_.patients.ecoc

当您插入带有可查询加密字段的文档时,MongoDB会更新元数据集合以维护一个允许查询的索引。该字段变为“索引字段”。每个此类字段都会在存储和写入速度上付出代价。

重要

当您删除加密集合时,立即删除相关的元数据集合

  • enxcol_.<collectionName>.esc

  • enxcol_.<collectionName>.ecoc

否则,重新创建具有相同名称的集合会使元数据集合处于冲突状态,消耗额外的存储空间并降低CRUD性能。

等值查询在存储和写入操作上具有固定的额外成本。范围查询成本取决于可查询字段的参数。紧密绑定这些查询可以大大降低其性能影响。

在插入文档时,每个索引字段需要向元数据集合写入两次。

  • 一次写入 ESC

  • 一次写入 ECOC

示例

插入具有两个索引字段的文档需要

  • 一次写入加密集合。

  • 四次写入元数据集合。

在更新文档时,每个索引字段需要向元数据集合写入两次。

  • 一次写入 ESC

  • 一次写入 ECOC

示例

更新具有两个索引字段的文档需要

  • 一次写入加密集合。

  • 四次写入元数据集合。

在删除文档时,索引字段不需要额外的写入。

在进行任何元数据压缩之前,ESCECOC 为每个索引字段的每个字段/值对包含一个元数据文档。在一个加密的字段/值对上索引 1000 个文档需要在 ESC 中占用 1000 个文档,并在 ECOC 中占用 1000 个文档。

注意

加密每个字段的可查询加密集合可能需要 2-3 倍的存储空间,以考虑元数据集合。例如,1 GB 的集合可能需要 2-3 GB 的存储空间。

  • 不要加密不需要加密的字段。大多数数据只需要加密一小部分字段,例如包含个人身份信息的字段。

  • 如果等价查询对于您的用户来说足够的话,不要在字段上启用范围查询。

  • 对于已启用范围查询的加密字段,请检查字段配置,特别是最小值、最大值精度参数。为范围查询设置严格的界限可以大大减少这些字段对性能的影响。

  • 对您的数据进行建模并对其进行原型设计,以确定您的部署的实际存储和写入增加。

当您插入或更新文档时,元数据集合会发生变化并增长。元数据集合压缩会清空 ECOC 并减小 ESC 的大小。

重要

在最坏的情况下,运行元数据压缩会揭示自上次压缩以来插入的所有文档中的唯一字段/值对数量。

有关元数据压缩揭示的准确信息,请参阅MongoDB的“第6节:理论分析”和“第9节:指南”可查询加密技术论文.

作为最佳实践,记录以下信息

  • encfields:每个文档的加密字段数量。

  • docinserts:自上次压缩以来插入的文档数量。

  • valinserts:自上次压缩以来插入的唯一字段/值对数量。

为了通过至少 t 个文档减小 ESC 元数据集合的大小,请在以下公式满足时运行元数据压缩

(encfields · docinserts) - valinsertst

每个文档的加密字段数量乘以自上次压缩以来的插入数量,减去自上次压缩以来插入的所有文档中的唯一字段/值对数量,应大于或等于要从 ESC 中删除的文档数量。

例如,在一个包含六个加密字段的集合中,当插入的总文档数和自上次压缩以来插入的唯一字段/值对满足以下条件时,可以至少减少1000个文档的ESC大小

(6 · docinserts) - valinserts1000

例如,如果自上次压缩以来插入了200个文档,其中所有文档中包含总共200个唯一的字段/值对,或者如果自上次压缩以来插入了400个文档,其中包含700个唯一的字段/值对,则该公式将得到满足。

您必须手动运行元数据压缩。使用 mongosh 并运行 db.collection.compactStructuredEncryptionData() 命令

示例

const eDB = "encryption"
const eKV = "__keyVault"
const secretDB = "records"
const secretCollection = "patients"
const localKey = fs.readFileSync("master-key.txt")
const localKeyProvider = { key: localKey }
const queryableEncryptionOpts = {
kmsProviders: { local: localKeyProvider },
keyVaultNamespace: `${eDB}.${eKV}`,
}
const encryptedClient = Mongo("localhost:27017", queryableEncryptionOpts)
const encryptedDB = encryptedClient.getDB(secretDB)
const encryptedCollection = encryptedDB.getCollection(secretCollection)
encryptedCollection.compactStructuredEncryptionData()
{
"stats": {
...
},
"ok": 1,
...
}

您可以使用 mongosh 和运行 db.collection.totalSize() 命令来检查元数据集合的大小。

示例

在这个示例中,加密集合被命名为 "patients"。

db.enxcol_.patients.esc.totalSize()
1407960328

返回

在创建集合时加密