65.9K
CodeProject 正在变化。 阅读更多。
Home

What the Shard? 使用 MongoDB .NET Driver 分区 Azure Cosmos DB

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (2投票s)

2018 年 8 月 3 日

CPOL

4分钟阅读

viewsIcon

14634

了解如何使用 C# MongoDB 驱动程序与 Azure Cosmos DB 对集合进行分区

引言

Azure Cosmos DB 是一个完全托管的 NoSQL 数据库。我在这篇博客上对其进行了广泛的介绍。一个高级且强大的功能是数据分区能力。这通常被称为分片。如果您遵循这些分区先决条件,Azure Cosmos DB 会为您处理此问题。

由于文档中已对此进行了充分的解释,我在这里不会过多介绍分区。简而言之,逻辑分区是分组在一起的项的范围。这由文档上的一个属性决定,该属性可以是哈希值或指定为范围。从逻辑上讲,具有相同分区键的项会放在一起。从物理上讲,一个节点可以存储一个或多个分区或分片。Azure Cosmos DB 会根据需求透明地为您处理此问题。

在此处阅读有关分区的全部知识:Azure Cosmos DB 中的分区和缩放

分区键有助于缩放,尤其是在数据库地理分布时。这是因为当插入或更新项时,复制可以专注于特定分区而不是整个数据库。通过将分区与这些读取进行共置,也可以优化读取。通过设置特定的一致性级别可以优化复制行为。

尽管文档讨论了分区如何在各种 API 中工作(有关可用数据库“风味”和不同 API 的概述,请阅读这篇Azure Cosmos DB API 概述),但没有明确的示例说明如何通过代码设置分区键。

我从我现有的USDA 数据库示例开始。其中包含近 9000 种食品项,它们被分配到特定的“食品组”。选择分区键有很多最佳实践。为了使此示例保持简单,我选择按 FoodGroupId 属性进行分区。

在 MongoDB 中创建集合的代码如下所示

await db.CreateCollectionAsync(collectionName);

要指定分区键,我们必须创建一个分片集合。这是通过向数据库发送命令来完成的。MongoDB 命令和查询都是 JSON 文档,因此我们可以使用驱动程序的 BsonDocument 类来构造命令。这是创建分片集合的命令

var partition = new BsonDocument {
    {"shardCollection", $"{db.DatabaseNamespace.DatabaseName}.{collectionName}"},
    {"key", new BsonDocument {{"FoodGroupId", "hashed"}}}
};
var command = new BsonDocumentCommand<BsonDocument>(partition);
await db.RunCommandAsync(command);

集合名称作为完全限定的数据库和集合名称传递,后跟分片键,该键指向 FoodGroupId 的哈希值。文档用于构造命令,然后将其传递给数据库。

插入数据后,您可以在门户中查看跨分区键的存储分布。

USDA 数据库的分区键

您可以看到有一些异常值占用了更多存储空间,但总的来说,存储是均匀分布的。您指定分区键来创建一个逻辑分区,该分区保证将具有相同键哈希值的项放在一起。Cosmos DB 会根据需要管理物理分区。在门户中,您可以看到,尽管我们有几十个分区键,但只有少数几个分区。

物理分区

分区是按顺序排列的。我重点介绍了“分区 3”,它存储了 40MB 的数据。单击分区会显示它包含的逻辑键。

物理分区 3 中的逻辑分区

集合中的每个文档都必须具有分区键,否则在尝试插入或更新它时会抛出错误。为了从性能和成本的角度了解分区的工作原理,我首先在整个数据库(多个物理分区和逻辑分区)中搜索文本“scrambled”。

跨分区查询
如果您对 MongoDB 查询中使用的 JSON 语法感到困惑,可以阅读更多关于它的信息以及它与 SQL 语法的关系:MongoDB 查询文档

请求单位 (RU) 代表完成操作所需的固定内存、存储和 CPU 量。在这里,运行查询的 RU 接近 4000。查询必须扫描所有项并应用正则表达式。让我们将其缩小到返回的两个唯一食品组。此查询将跨越两个逻辑分区,并且碰巧跨越两个物理分区(0100 在与 2100 不同的分区上)。

缩小到两个分区

过滤器显著减少了 RU,但这主要是因为查询引擎利用内置索引来缩小要扫描的项的范围。如果我们仅限于单个分区(逻辑和物理),性能将再次显著提高。

单个分区

性能优势不仅仅在于扫描的记录数量有限。我们可以使用一个不是分区键的列(组描述,而不是其唯一标识符)将记录限制为完全相同的子集,RU 会增加,因为它不限于单个分区。

不使用分区键时的相同过滤器

对于兆字节的数据,这种增加并不那么显著,但在处理 PB 和 TB 数据时会更加明显。

如果您正在从 MongoDB 迁移到 Azure Cosmos DB,或者仅仅对使用 MongoDB API 感兴趣,那么您现在知道如何利用分区键来实现 Azure Cosmos DB 的大规模复制。对于其他 API,概念是相似的,但实现方式有所不同。

准备好开始使用 MongoDB API 了吗?阅读使用 MongoDB API 入门 Azure Cosmos DB

© . All rights reserved.