我在尝试对数据进行建模时遇到了麻烦,以至于我可以有效地查询Cassandra最近修改的最后10个(实际上是任何数量)记录.每个记录都有一个last_modified_date列,由应用程序在插入/更新记录时设置.
我已从此示例代码中排除了数据列.
主数据表(每条记录只包含一行):
CREATE TABLE record (
record_id int,
last_modified_by text,
last_modified_date timestamp,
PRIMARY KEY (record_id)
);
Run Code Online (Sandbox Code Playgroud)
我试图创建一个单独的表,它使用了一个聚类键顺序.
表(每条记录一行;仅插入最后修改日期):
CREATE TABLE record_by_last_modified_index (
record_id int,
last_modified_by text,
last_modified_date timestamp,
PRIMARY KEY (record_id, last_modified_date)
) WITH CLUSTERING ORDER BY (last_modified_date DESC);
Run Code Online (Sandbox Code Playgroud)
查询:
SELECT * FROM record_by_last_modified_index LIMIT 10
Run Code Online (Sandbox Code Playgroud)
此解决方案不起作用,因为群集顺序仅适用于具有相同分区键的记录的排序.由于每行具有不同的分区键(record_id),因此查询结果不包括预期记录.
我尝试的另一个解决方案是简单地查询Cassandra的所有record_id和last_modified_date值,对它们进行排序并选择我的应用程序中的前10条记录.这显然效率低下,并且不能很好地扩展.
我考虑的最后一个解决方案是对所有记录使用相同的分区键,并使用聚类顺序确保记录正确排序.该解决方案的问题在于,数据将无法在节点之间正确分区,因为所有记录都具有相同的分区键.这对我来说似乎不是一件好事.
Jim*_*yer 16
我认为你要做的更多的是关系数据库模型,而且在Cassandra中有点反模式.
Cassandra只根据聚类列对事物进行排序,但排序顺序不会发生变化.这是因为当memtables作为SSTables(Sorted String Tables)写入磁盘时,SSTable是不可变的,无法有效地重新排序.这就是不允许您更新群集列的值的原因.
如果要对群集行重新排序,我知道的唯一方法是删除旧行并在批处理中插入新行.为了使效率更低,您可能需要首先读取以找出last_modified_date对于record_id的内容,以便您可以删除它.
所以我会寻找一种不同的方法,例如将更新写为新的聚簇行并将旧的那些留在那里(可能使用TTL随时间清理它们).因此,当您执行LIMIT查询时,您的最新更新将始终位于顶部.
在分区方面,您需要将数据分成几个类别,以便在节点上传播数据.这意味着您不会对表进行全局排序,而只是在类别中,这是由分布式模型引起的.如果你真的需要全局排序,那么或许看看像Cassandra和Spark一样的东西.排序在时间和资源上非常昂贵,因此请仔细考虑是否真的需要它.
更新:
考虑到这一点,您应该能够使用物化视图在Cassandra 3.0中执行此操作.该视图将处理杂乱删除并为您插入,以重新排序群集行.所以这是3.0 alpha版本中的样子:
首先创建基表:
CREATE TABLE record_ids (
record_type int,
last_modified_date timestamp,
record_id int,
PRIMARY KEY(record_type, record_id));
Run Code Online (Sandbox Code Playgroud)
然后使用last_modified_date作为聚类列创建该表的视图:
CREATE MATERIALIZED VIEW last_modified AS
SELECT record_type FROM record_ids
WHERE record_type IS NOT NULL AND last_modified_date IS NOT NULL AND record_id IS NOT NULL
PRIMARY KEY (record_type, last_modified_date, record_id)
WITH CLUSTERING ORDER BY (last_modified_date DESC);
Run Code Online (Sandbox Code Playgroud)
现在插入一些记录:
insert into record_ids (record_type, last_modified_date, record_id) VALUES ( 1, dateof(now()), 100);
insert into record_ids (record_type, last_modified_date, record_id) VALUES ( 1, dateof(now()), 200);
insert into record_ids (record_type, last_modified_date, record_id) VALUES ( 1, dateof(now()), 300);
SELECT * FROM record_ids;
record_type | record_id | last_modified_date
-------------+-----------+--------------------------
1 | 100 | 2015-08-14 19:41:10+0000
1 | 200 | 2015-08-14 19:41:25+0000
1 | 300 | 2015-08-14 19:41:41+0000
SELECT * FROM last_modified;
record_type | last_modified_date | record_id
-------------+--------------------------+-----------
1 | 2015-08-14 19:41:41+0000 | 300
1 | 2015-08-14 19:41:25+0000 | 200
1 | 2015-08-14 19:41:10+0000 | 100
Run Code Online (Sandbox Code Playgroud)
现在我们更新基表中的记录,并且应该看到它移动到视图中列表的顶部:
UPDATE record_ids SET last_modified_date = dateof(now())
WHERE record_type=1 AND record_id=200;
Run Code Online (Sandbox Code Playgroud)
所以在基表中,我们看到record_id = 200的时间戳已更新:
SELECT * FROM record_ids;
record_type | record_id | last_modified_date
-------------+-----------+--------------------------
1 | 100 | 2015-08-14 19:41:10+0000
1 | 200 | 2015-08-14 19:43:13+0000
1 | 300 | 2015-08-14 19:41:41+0000
Run Code Online (Sandbox Code Playgroud)
在视图中,我们看到:
SELECT * FROM last_modified;
record_type | last_modified_date | record_id
-------------+--------------------------+-----------
1 | 2015-08-14 19:43:13+0000 | 200
1 | 2015-08-14 19:41:41+0000 | 300
1 | 2015-08-14 19:41:10+0000 | 100
Run Code Online (Sandbox Code Playgroud)
因此,您会看到record_id = 200在视图中向上移动,如果您在该表上执行了N限制,则会获得N个最近修改过的行.
| 归档时间: |
|
| 查看次数: |
5973 次 |
| 最近记录: |