关于为存储用户数据的分区键选择最佳(语义)值,我有一个难题。
用户文档具有: -ID(GUID) -电子邮件(例如用于登录) -个人资料数据
主要有2种查询类型:
id
查找用户(大多数查询)email
查找用户(登录和一些管理员查询)我想避免跨分区查询。
如果我为id
(综合字段)选择partitionKey
,则登录查询将是跨分区的。
另一方面,如果我选择email
,那么如果用户曾经更改过电子邮件-这是一个问题。
我的想法是在集合中引入新类型。像这样:
userId: guid,
userEmail: “email1”,
partitonKey: “users-mappings”
然后我可以将User
文档本身设置为:
id: someguid,
type: “user”,
partitionKey: “user_someguid”,
profileData: {}
以这种方式,当用户登录时,我首先通过email
检查映射类型/分区,获取guid
,然后通过User
检查实际的guid
文档。
此外,通过这种方式可以更改电子邮件而不会影响分区。
这是有效的方法吗?有什么问题吗?我想念什么吗?
答案 0 :(得分:1)
您的问题没有标准答案。我认为,名为mapping type
的解决方案会导致两个查询效率低下。选择分区密钥始终是平衡利弊的过程。请参阅官方文档中的guidance。
根据您的描述:
1。按ID查找用户(大多数查询)
2。通过电子邮件查找用户(登录和一些管理员查询)
我建议您优先考虑最频繁的查询,即id
。
我的原因:
1.id不会轻易更改,相对稳定。
2。会话或cookie可以在登录后保存,因此与id相同的登录权限很少。
3.id是您最常查询的条件,因此不可能每次都跨越所有分区。
4。如果您确实担心登录性能,请不要忘记为email
列添加indexing policy。这也可以提高性能。
答案 1 :(得分:1)
您已经知道,在查询Cosmos DB中,扇出应该是查询的最后一个选项,尤其是在诸如登录之类的大批量操作时。此外,使用大数据时,RU的成本将明显更高。
在Cosmos DB SQL API中,一种模式是使用合成分区键。您可以通过将ID和写入时的电子邮件连接起来来组成合成分区键。此模式适用于提供灵活性的众多查询方案。
类似这样的东西:
{
"id": "123",
"email":"joe@abc.com",
"partitionKey":"123-joe@abc.com"
}
然后在阅读时,执行以下操作:
SELECT s.something
FROM s
WHERE STARTSWITH(s.partitionKey, "123")
OR
ENDSWITH(s.partitionKey, "joe@abc.com")
您还可以使用SUBSTRING()等...
使用上述方法,您可以通过用户的 id 或电子邮件来搜索用户,并且仍然可以使用分区键的效率,从而最大程度地减少查询RU成本和优化性能。