在Cassandra中创建自己的索引表时,执行原始查询的最佳方法是什么?

时间:2017-11-09 14:30:21

标签: cassandra

假设我有一张表格,其中存储的视频如下:

CREATE TABLE videos (
    video_id UUID,
    created_date TIMESTAMP,
    description TEXT,
    title TEXT,
    user_id UUID,
    tags LIST<TEXT>
    PRIMARY KEY(video_id)
);

我希望能够获得标记为&#34;有趣&#34;标签。但我希望将每个结果限制为20,并从那里分页。

所以我制作了一个tag_index表

CREATE TABLE tag_index (
    tag TEXT,
    video_id UUID
    PRIMARY KEY (tag, video_id)
);

每次插入带有3个标签的新视频时,我会进行4次插入,1次为视频,3次为标记。每次标记视频时,我都会在tag_index表中插入一个新标记。

但我该如何进行查询?

我会首先在tag_index表中进行查询并得到20个video_id的结果,然后对视频表执行另一个查询,并使用我从第一个查询获得的所有video_id执行IN子句吗?或者我会在视频表上执行20个单选查询?这对我来说似乎不是很有效,或者我错了吗?

我如何以最好的方式做到这一点?我不明白如何以一种很好的方式使用这个自制的索引表,这是Cassandra的最佳实践。

2 个答案:

答案 0 :(得分:1)

多表是正确的方法。

现在您的辅助查询Select * FROM videos WHERE video_id in (1,2,3...);这在cassandra世界中也没问题,但我会避免它。

您将要查询协调器节点,然后该节点将确定哪些节点拥有20个视频,针对每个节点运行查询(可能是那里的读取修复,如果您运行了仲裁,则会有一些额外的查询)等)然后组装并返回给你。这有很多网络流量。

Cassandra在读取方面不是很好,写入很便宜,它压缩数据。 相反,我会将所有视频数据移动到标签表中,并在视频表中复制它以减少查找。

CREATE TABLE video_with_tags (
    tag TEXT,
    video_id UUID,
    created_date TIMESTAMP,
    description TEXT,
    title TEXT,
    user_id UUID,
    PRIMARY KEY (tag, video_id)
);

现在您的查询看起来像Select * from videos_with_tags WHERE tag = 'x';数据位于一个节点上,而且速度会更快。

您仍然会维护视频表,因此如果您需要进行维护(视频和标签上的CRUD),您可以找到其他标签数据等。

记住cassandra不是RDBMS,加入是一件事,3NF不是一件事。在更新上写入多个表是可以的。

答案 1 :(得分:0)

方法#1:

当您执行大查询时,这意味着您正在等待这个单一协调器节点给您一个响应,它将所有这些查询及其响应保留在堆中,如果其中一个查询失败,或者协调器失败,你必须重试整个事情

因此,不要使用单个IN查询,而是使用execute async为每个video_id使用单独的查询来获取video_id的详细信息。

示例:

//Prepared only once
PreparedStatement statement = session.prepare("SELECT * FROM videos WHERE video_id = ?");

//List<UUID> videoIDs;// You already have the video ids

List<ResultSetFuture> futures = new ArrayList<>();
for (UUID videoID : videoIDs) {
    ResultSetFuture resultSetFuture = session.executeAsync(statement.bind(videoID));
    futures.add(resultSetFuture);
}

for (ResultSetFuture future : futures){
     ResultSet rows = future.getUninterruptibly();
     Row row = rows.one();
     //Now you have the video details in the row     
}
  

Cassandra Query Patterns: Not using the “in” query for multiple partitions.

注意:大量的执行异步会导致超时异常

方法#2:

将您的架构归一化为@Highstead Suggested

注意:如果您对表进行非规范化,则必须保持它们之间的一致性。每当发生任何更新时,如果更新了视频标题,则必须更新非正规化时所做的所有副本