我决定为我的文档实施以下ID策略,该策略将文档“type”与ID结合起来:
doc.id = "docType_" + Guid.NewGuid().ToString("n");
// create document in collection
这会为我的文档生成以下ID:
usr_19d17037ea7f41a9b20db1a90f71d30d
usr_89fe82c93b264076aa1b6e1fb4813aaf
usr_2aa58c1c970a4c5eaa206a755c1c7bf4
msg_ec43510732ae47a6a5d5f323b7461d68
msg_3b03ceeb7e06490d998c3e368b435851
如果ID上有RangeIndex
策略,我应该能够查询集合中的特定类型。例如:
SELECT * FROM c WHERE STARTSWITH(c.id, 'usr_') AND ...
由于这是一个包含许多不同文档类型的Web应用程序,因此我的应用程序的许多查询默认会实现此STARTSWITH
过滤器。
我主要关注的是在ID上使用随机GUID字符串。我知道在SQL Server中,当在聚簇索引中的主键上使用随机GUID时,我遇到了索引性能和碎片问题。
这里有类似的问题吗?似乎在DocumentDB中,管理索引的注意事项已从您身上抽象出来。顺序ID会以任何方式更理想/更高效吗?
答案 0 :(得分:5)
tl; dr:为类型和仅GUID ID使用单独的字段,并在两者上使用哈希索引。
根据您问题的性质,这个答案必然会有些根据。让我首先解决一下您的主要关注点,即影响性能的索引碎片化。
DocumentDB假定使用GUID和哈希索引(而不是范围索引)非常适合通过GUID查找一个匹配的实体。另一方面,如果你想通过查看字符串的开头找到一组文档,我怀疑使用范围索引可能会更高效。这假设STARTSWITH仅在与范围索引一起使用时进行了优化,但我不知道即使你有范围索引它也会被优化。
我的建议是为类型和GUID-only ID使用单独的字段,并在两者上使用哈希索引。这样可以确保您所展示的查询具有高性能,并且将类型子句与其他参数组合在一起的查询也可以使用至少一个索引。请注意,此类型的哈希索引(例如2x 3字节= 6字节/文档)具有很高的空间效率,因此不必担心需要其中的两个。这两个组合应该远小于一个范围索引,它需要有足够的精度来覆盖你的类型+ GUID的整个长度。
除了已经讨论过的性能和空间原因之外,我还可以看到将类型与GUID组合时的其他一些缺点:1)尝试检索单个文档时(直接使用和作为外键的一部分)查找),使GUID分离并使用哈希索引将比在组合字段上使用范围索引更快且更节省空间; 2)将类型与ID组合使得通常需要在以后完成的某些迁移变得非常复杂。假设您决定将用户分为作者和读者。用户是用户ID在其他文档类型(博客文章作者,读者评论等)中引用的外键。如果该ID包含类型,那么您不仅需要更改用户文档以完成迁移,还需要查找和更改每个外键。如果两个字段(GUID和类型)是分开的,那么您只需要更改用户文档。敏捷软件工艺主要是为了做出能够提供灵活性的决策。
对于顺序索引的使用,一般数据库和特别是NoSQL的趋势是提供单调递增的顺序ID的复杂性大于GUID上的空间效率优势。如果您要坚持使用DocumentDB,我建议您使用流程并使用GUID。