我们正在.NET中构建REST API,并将其部署到Azure App Service / Azure API App。客户端可以通过此API创建“产品”并查询“产品”。产品实体具有一组通用字段,所有客户在创建产品时都必须提供这些字段,例如以下字段(示例)
{
"id": "cbf3f7aa-4743-4198-b307-260f703c42c1"
"name": "Product One"
"description": "The number one product"
}
我们目前将这些产品作为独立文件存储在Azure Cosmos DB中。
问题1:分区。 该馆藏将不会存储大量文件,我们谈论的最大数量约为2 500 000个文件,每个文件在1-5 kb之间(估计)。当前,我们选择了id字段(这是我们的系统生成的id,而不是内部Cosmos DB文档的id)作为分区键,这意味着2 500 000逻辑分区,每个分区一个文档。这些文档将用于某些低延迟的工作负载中,但是这些工作负载将按id(分区键)进行查询。客户还将通过名称,然后我们有一个扇出查询,但是这些查询对延迟不是至关重要的。在门户中,您无法再创建单个分区集合,但是可以从SDK中进行操作,也可以具有固定的分区键值。如果将所有这些文档都放在一个分区中(此处讨论的数据远低于10 GB),我们将永远不会获得任何扇出查询,而是更多地依赖一个逻辑分区中的索引。所以问题来了:即使我们没有大量数据,像我们目前所做的那样进行分区还是明智的?
问题2:扩展元数据。 我们将面对想要在基本公共字段之外编写客户/应用程序/特定于客户的元数据的客户。做这个的最好方式是什么?
下面有一些我的头脑风暴。
一个选项是允许API中的客户端在创建产品时添加带有键值对的嵌套“ extendedMetadata”字段类型。 Cosmos DB与模式无关,因此从理论上讲应该可以正常工作。一些产品可以具有零个扩展元数据,而其他产品可以具有很多扩展元数据。对于客户,我们可以保证基本的公共字段,但是对于扩展元数据字段,我们不能保证在字段数量,命名等方面有任何要求。然后,文档大小将有所不同。如前所述,这些产品仍将用于关键延迟的工作负载中,这些工作负载将通过“ id”(分区键)进行查询。扩展的元数据将永远不会用于任何关键延迟的工作负载中。大小/性能/吞吐量?对于延迟关键的读取方案,查询优化器将直接转到正确的分区,然后使用索引快速检索感兴趣的文档字段,或者整个文档始终独立加载和处理。您要查询哪些字段?
{
"id": "cbf3f7aa-4743-4198-b307-260f703c42c1"
"name": "Product One"
"description": "The number one product"
"extendedMetadta" : {
"prop1": "prop1",
"prop2": "prop2",
"propN": "propN"
}
}
扩展的元数据仅在某些情况下可用于从相同的API检索。然后我们可以做类似的事情:
一个选择可能是进行某种拆分。如果API的客户端创建了一个包含扩展元数据的产品,那么如果extendedMetadata包含数据,我们可以实现一些逻辑来拆分文档。我猜想拆分可以通过多种方式完成,下面是集思广益。我猜想拆分文档的主要目的(在写操作上需要做更多的工作)是为了在文档大小在这里起重要作用的情况下获得更好的吞吐量(在大多数情况下,客户可以使用基本的公共字段)。
很长的帖子很抱歉。希望这是可以理解的,期待您的反馈!
答案 0 :(得分:0)
答案1:
如果您可以保证文档的总大小不会超过10GB,那么创建固定集合是有两个理由。 首先,不需要跨分区查询。我并不是说无需分区即可快速实现闪电,而是因为您只是在进行交互 有了一个简单的物理分区,它将比在每个单独的物理分区中查找数据要快。
(但是请记住,每当人们认为他们可以保证某物的最大尺寸之类的东西时,通常都无法解决问题。)
/ id分区策略仅在您始终可以提供id时才有效。这称为读取。如果您需要按任何其他属性进行搜索,这意味着 您正在执行查询。这是系统做不到的地方。
理想情况下,您应该以一种永不做跨分区查询的方式设计Cosmos DB集合,这是日常工作量的一部分。出于报告的原因,也许曾经是个蓝月亮。
答案2:
出于某种原因,Cosmos DB是一种无SQL架构的数据库。 头脑风暴的第二种方法是适合传统的RDBMS数据库,但我们这里没有。 您可以简单地采用第一种方法,将所有内容都放在一个属性下,也可以将它们放在顶层。
请记住,您可以将响应映射到所需的任何对象,因此您只需拥有2个DTO。纤薄和扩展版本 并根据端点映射到不同的版本。
希望这会有所帮助。