4

我们的团队已经开始开发一个由 Couchbase DB 支持的应用程序;对于我们每个人来说,这是第一次使用非 SQL 数据库。

我们已经开始定义我们的实体并采用 Couchbase 手册建议的使用“类型”前缀的做法:

Entity "A":
key: a#123

Entity "B":
key: b#123

但是我们意识到我们对选择创建复合文档键的策略感到困惑。我们经常使用柜台,他们需要自己的文件。我们的密钥变得复杂了:

Daily counter "x" for entity "A":
key: cntrx#a#123-20140117

我们已经考虑了不同的方法,但我们仍然是这个主题的新手,想请教一些建议。

分层键有什么好处吗?任何人都可以分享他们定义重要密钥的最佳实践吗?

4

2 回答 2

4

在我们的项目中,我们以如下所述的方式使用分层键:键的第一部分类似于 RDBMS 中的表名: users- 表示“表”

然后每个用户都有自己的 id,例如:

users:1- “代表一个用户”

我们使用了 ':',因为我认为它看起来比其他分隔符更好。您可以使用任何您喜欢的分隔符。

如果你想像id前面的例子一样使用顺序索引,你需要从某个键中获取它们,所以:

users:counter- 保存“最后一个用户 ID”的键(它的作用类似于自动增量)

如果您需要为用户帐户存储一些“小节”,您可以存储它:

users:<user's id>:subsection.

更复杂的例子

users:1:avatars:1:url- 表示通过此键我们将获得用户 1 的头像 url,但如果用户想要存储许多头像,他们将进入users:1:avatars:X:url,其中 X 将是users:1:avatars:counter键的值。

我们对所有文档都使用了这种策略,它们只存储一个值、JSON 甚至二进制数据。

因此,对于您的示例,我将选择:

a:123-20140117:counter- 这将意味着我们有(以 RDBMS 语言说话)名为“a”的表,在表“a”中,我们有 ID(或其他)“123-20140117”的记录,其字段为“cntrx”。

UPD: 关于密钥大小。其实没关系。是的,密钥的大小是有限的,但是有很多方法可以减小它。其中之一 - 使用哈希,但我认为这是不好的方法,因为键会很长并且会消耗更多内存。在我们的项目中,我们为 memcached 存储桶使用了“短”键。我们有一个枚举(也可以存储在 couchbase 中),它代表人类可以理解的键名,它是缩短值。

示例:我们有一些记录:拥有超过 30 张照片的用户列表。所以我们有一个键值对:

usersByPhotosCount - k:ubpc:{0}

30 张照片的关键是k:ubpc:30.

但最好只在生产中进行此类优化。在开发中,最好在应用程序和数据库中使用可理解的密钥(即,您可以创建两组 kv 对:正常用于开发,缩短和混淆用于生产,并根据您的环境加载它们)。

于 2014-01-17T15:43:41.793 回答
2

关于你的问题,我有几点建议。

全面的

Nosql 就像它听起来一样 - 并且需要与以前用于设计良好 SQL 数据库的思维方式大不相同。例如,一个 nosql 数据库基本上是一个大的哈希映射。因此,尽管考虑到您的密钥(例如使它们变小)可能会很好,但请记住它们只是访问您的文档的一种方式。除非让它们看起来具有某种特定的优势,否则它们根本不需要任何意义——通常总是首先需要一个主查找。例如,您的用户多久会知道他们需要在导航到您的应用时直接询问“b#123”?我认为这是有利的唯一地方是用户名或用户会知道的其他一些数据。

复合键

虽然 CB 手册可能建议复合键是一个好主意(它们很可能适用于简单的数据库结构),但一般来说,键大小应尽可能小。密钥被限制为最多 256 个字节。所有密钥都必须存储在 RAM 中——因此密钥中的数据越多,其余数据可用的数据就越少。相反,我建议在您的文档中创建一个类型字段,然后使用视图提取特定类型的对象(或按类型索引对象)。这最终将为您提供更大的灵活性。

计数器

您对计数器的解释相当模糊,所以我假设您将它们用作自动增量键。我建议这里需要改变方法以摆脱柜台。我对数据库中的所有键使用唯一标识符。当我使用复合键时,这是因为键本身很重要(例如,在受修订控制的文档中,我使用文档 id + 文档保存日期的复合键来确保它是唯一的)。即使您有数百万(甚至数十亿)个对象,您也可以使用 12 字节的 GUID 来实际保证文档 ID 的唯一性。当需要保存新记录时,这可以防止应用程序中出现非常糟糕的瓶颈。

于 2014-01-18T04:37:40.293 回答