Docs 菜单
Docs 主页
/
MongoDB Manual
/ / / / /

加密collection

在此页面上

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

字段级加密会带来性能和存储成本。 您选择加密的每个字段:

  • 在插入和更新操作中添加写入。

  • 需要额外的存储,因为MongoDB维护加密字段的索引以提高查询性能。

本节总结了加密集合的存储和写入影响,并说明了如何压缩加密的集合索引以最大限度地降低这些成本。 如果要加密字段并配置它们以进行查询,请参阅加密字段和启用的查询。

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

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

  • 两个元数据集合

  • 在加密collection中每个文档的字段叫做 __safeContent__

警告

不得修改或删除这些数据结构,这一点至关重要,否则查询结果将不正确。

创建加密集合时,MongoDB 会创建两个元数据集合:

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

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

例子

如果创建名为“患者”的集合,MongoDB 将创建以下元数据集合:

  • enxcol_.patients.esc

  • enxcol_.patients.ecoc

当您插入具有可查询加密字段的文档时,MongoDB 会更新元数据集合以维护支持查询的索引。该字段将成为“索引字段”。 这是以每个此类字段的存储和写入速度为代价的。

重要

删除加密集合时,请立即删除关联的元数据集合:

  • enxcol_.<collectionName>.esc

  • enxcol_.<collectionName>.ecoc

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

相等查询会给存储和写入操作带来固定的额外成本。 范围查询成本取决于可查询字段的参数。 严格限制这些查询可以大大降低它们对性能的影响。

插入文档时,每个索引字段都需要对元数据集合进行两次额外写入。

  • 一个写入 ESC

  • 一个写入 ECOC

例子

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

  • 对加密collection的一次写入。

  • 四次写入元数据集合。

更新文档时,每个索引字段都需要对元数据集合进行两次额外写入。

  • 一个写入 ESC

  • 一个写入 ECOC

例子

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

  • 对加密collection的一次写入。

  • 四次写入元数据集合。

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

在进行任何元数据压实之前, ESCECOC会为每个索引字段的每个字段/值对包含一个元数据文档。 在 文档中为一个加密字段/值对建立索引需要1000 1000中的ESC 文档和1000 中的 文档。ECOC

注意

考虑到元数据集合,对每个字段进行加密的可查询Queryable Encryption集合最多可能占用2 - 3倍的存储空间。 示例,一个1 GB的集合可能具有2 - 3 GB的存储要求。

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

  • 如果相等查询对用户来说已经足够,则不要对字段启用范围查询。

  • 对于启用了范围查询的加密字段,请查看字段配置,尤其是最小值、最大值精度参数。 为范围查询设置严格边界可以大大降低这些字段对性能的影响。

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

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

重要

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

有关元数据压实所揭示的确切信息的详细信息,请参阅 MongoDB 的 Queryable Encryption技术论文中的“第6节:理论分析”和“第9节:指南”。

最佳实践是,请追踪以下信息:

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

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

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

要将ESC元数据集合的大小减少至少t文档,请在满足以下公式时运行元数据压实:

( encfields · docinserts ) - valinsertst

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

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

( 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()命令来检查元数据集合的大小。

例子

在此示例中,加密collection名为“患者”。

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

后退

在创建时加密集合