DocumentDB索引性能/碎片

ksp*_*rin 2 azure-cosmosdb

我决定为我的文档实现以下ID策略,它将文档"type"与ID结合起来:

doc.id = "docType_" + Guid.NewGuid().ToString("n");

// create document in collection
Run Code Online (Sandbox Code Playgroud)

这会为我的文档生成以下ID:

usr_19d17037ea7f41a9b20db1a90f71d30d
usr_89fe82c93b264076aa1b6e1fb4813aaf
usr_2aa58c1c970a4c5eaa206a755c1c7bf4
msg_ec43510732ae47a6a5d5f323b7461d68
msg_3b03ceeb7e06490d998c3e368b435851

通过RangeIndexID上的策略,我应该能够查询集合中的特定类型.例如:

SELECT * FROM c WHERE STARTSWITH(c.id, 'usr_') AND ...
Run Code Online (Sandbox Code Playgroud)

由于这是一个包含许多不同文档类型的Web应用程序,因此我的应用程序的许多查询都会STARTSWITH默认实现此过滤器.

我主要关心的是在ID上使用随机GUID字符串.我知道在SQL Server中,我在使用聚簇索引中的主键上的随机GUID时遇到了索引性能和碎片问题.

这里有类似的问题吗?似乎在DocumentDB中,管理索引的注意事项已从您身上抽象出来.顺序ID会以任何方式更理想/更高效吗?

Lar*_*one 5

tl; dr:为类型和GUID-only ID使用单独的字段,并在两者上使用哈希索引.

根据您的问题的性质,这个答案必然会有所不同.让我首先解决一下您的主要关注点,即影响性能的索引碎片化.

DocumentDB假定使用GUID和哈希索引(而不是范围索引)非常适合通过GUID查找一个匹配的实体.另一方面,如果你想通过查看字符串的开头找到一组文档,我怀疑使用范围索引可能会更高效.这假设STARTSWITH仅在与范围索引一起使用时进行了优化,但我不知道即使您有范围索引也会对其进行优化.

我的建议是为类型和GUID-only ID使用单独的字段,并在两者上使用哈希索引.这样可以确保您所展示的查询具有高性能,并且将类型子句与其他参数组合在一起的查询也可以使用至少一个索引.请注意,此类型的哈希索引(例如2x 3字节= 6字节/文档)具有很高的空间效率,因此不必担心需要其中的两个.这两个组合应该远小于一个范围索引,它需要有足够的精度来覆盖你的类型+ GUID的整个长度.

除了已经讨论过的性能和空间原因之外,我还可以看到将类型与GUID结合起来的其他一些缺点:1)在尝试检索单个文档时(直接使用和作为外键查找的一部分),将GUID分开并使用哈希索引将比在组合字段上使用范围索引更快且更节省空间; 2)将类型与ID组合使得通常需要在以后完成的某些迁移变得非常复杂.假设您决定将用户分为作者和读者.用户是用户ID在其他文档类型(博客文章作者,读者评论等)中引用的外键.如果该ID包含该类型,那么您不仅需要更改用户文档以完成迁移,而且还需要 d还需要查找和更改每个外键.如果两个字段(GUID和类型)是分开的,那么您只需要更改用户文档.敏捷软件工艺主要是为了做出能够提供灵活性的决策.

至于顺序索引的使用,一般数据库和特别是NoSQL的趋势是提供单调增加的顺序ID的复杂性大于GUID上的空间效率优势.如果您要坚持使用DocumentDB,我建议您使用流程并使用GUID.