Cassandra:反规范化和分页
Cassandra: denormalization and paging
我正在尝试了解并熟悉 Cassandra 数据模型。
本文解释了一些基本的建模规则:
https://www.ebayinc.com/stories/blogs/tech/cassandra-data-modeling-best-practices-part-1/
选项 3 显示非规范化数据模型:
我做对了吗,"user_by_item" table 具有以下结构?
CREATE TABLE "user_by_item" (
item_id int,
users list<User>
PRIMARY KEY (item_id)
)
如果是:很明显我可以通过 item_id 通过一次查询获得所有用户。但是那时不可能翻阅用户列表。
我是否正确理解了 table 结构以及如何管理项目列表,尤其是当它们变得非常大时?
首先,那篇文章已有 6 年历史了。在当时,这是一篇很棒的文章,但 Cassandra 从那以后发生了 显着 的变化。例如,Cassandra 1.1 中不存在集合,我 认为 是撰写本文时的 most-recent 版本。
Am I getting the things right, that the "user_by_item" table has the following structure?
是的,我想你已经明白了。使用 item_id 作为 users_by_item 上的单个 PRIMARY KEY
,同时将用户存储为集合是您可以执行此操作的一种方式。但是,它限制了您的查询灵活性,无法一次拉回所有用户。
构建该查询 table 的最 query-friendly 方法可能是在 user_id
:[=21= 上使用聚簇键]
CREATE TABLE user_by_item (
item_id int,
user_id int,
email text,
name text,
PRIMARY KEY ((item_id),user_id)
);
这样,我可以查询与项目 111 关联的所有用户:
aploetz@cqlsh:Whosebug> SELECT * FROM user_by_item WHERE item_id=111;
item_id | user_id | email | name
---------+---------+---------+------
111 | 123 | jp@ebay | Jay
111 | 456 | jd@ebay | John
(2 rows)
我也可以只查询 Jay,如果我知道他的话 user_id
:
aploetz@cqlsh:Whosebug> SELECT * FROM user_by_item WHERE item_id=111
AND user_id=123;
item_id | user_id | email | name
---------+---------+---------+------
111 | 123 | jp@ebay | Jay
(1 rows)
这给了我更多的查询灵活性,同时还存储了 item_id
的所有用户数据。
亲提示:
- 除非万不得已,否则不要将您的 table 名称用双引号引起来。它迫使 Cassandra 维持它的大小写,但会使以后的数据检索成为一种令人沮丧的体验。
- 在为 Cassandra 建模时,通常的做法是使用像
name
= "Jay." 这样的自然键从主 table 中引用,而不会冒着每次 needed/stored 都被拼错的风险。在 Cassandra 中我们没有外键之类的东西,所以自然键可以帮你剪掉一些不需要的列。
- Cassandra 中的主键无法更改。因此,上述规则的例外情况是,如果预测主键值会发生变化(例如,Jay 合法地更改了他的
name
),那么使用代理键就成了一个好主意。
我正在尝试了解并熟悉 Cassandra 数据模型。 本文解释了一些基本的建模规则:
https://www.ebayinc.com/stories/blogs/tech/cassandra-data-modeling-best-practices-part-1/
选项 3 显示非规范化数据模型:
我做对了吗,"user_by_item" table 具有以下结构?
CREATE TABLE "user_by_item" (
item_id int,
users list<User>
PRIMARY KEY (item_id)
)
如果是:很明显我可以通过 item_id 通过一次查询获得所有用户。但是那时不可能翻阅用户列表。
我是否正确理解了 table 结构以及如何管理项目列表,尤其是当它们变得非常大时?
首先,那篇文章已有 6 年历史了。在当时,这是一篇很棒的文章,但 Cassandra 从那以后发生了 显着 的变化。例如,Cassandra 1.1 中不存在集合,我 认为 是撰写本文时的 most-recent 版本。
Am I getting the things right, that the "user_by_item" table has the following structure?
是的,我想你已经明白了。使用 item_id 作为 users_by_item 上的单个 PRIMARY KEY
,同时将用户存储为集合是您可以执行此操作的一种方式。但是,它限制了您的查询灵活性,无法一次拉回所有用户。
构建该查询 table 的最 query-friendly 方法可能是在 user_id
:[=21= 上使用聚簇键]
CREATE TABLE user_by_item (
item_id int,
user_id int,
email text,
name text,
PRIMARY KEY ((item_id),user_id)
);
这样,我可以查询与项目 111 关联的所有用户:
aploetz@cqlsh:Whosebug> SELECT * FROM user_by_item WHERE item_id=111;
item_id | user_id | email | name
---------+---------+---------+------
111 | 123 | jp@ebay | Jay
111 | 456 | jd@ebay | John
(2 rows)
我也可以只查询 Jay,如果我知道他的话 user_id
:
aploetz@cqlsh:Whosebug> SELECT * FROM user_by_item WHERE item_id=111
AND user_id=123;
item_id | user_id | email | name
---------+---------+---------+------
111 | 123 | jp@ebay | Jay
(1 rows)
这给了我更多的查询灵活性,同时还存储了 item_id
的所有用户数据。
亲提示:
- 除非万不得已,否则不要将您的 table 名称用双引号引起来。它迫使 Cassandra 维持它的大小写,但会使以后的数据检索成为一种令人沮丧的体验。
- 在为 Cassandra 建模时,通常的做法是使用像
name
= "Jay." 这样的自然键从主 table 中引用,而不会冒着每次 needed/stored 都被拼错的风险。在 Cassandra 中我们没有外键之类的东西,所以自然键可以帮你剪掉一些不需要的列。 - Cassandra 中的主键无法更改。因此,上述规则的例外情况是,如果预测主键值会发生变化(例如,Jay 合法地更改了他的
name
),那么使用代理键就成了一个好主意。