我创建了一个 REST API,其架构如下所示:
type Todo struct {
ID gocql.UUID `json:"id"`
User_ID string `json:"user_id"`
Title string `json:"title"`
Description string `json:"description"`
Status string `json:"status"`
Created time.Time `json:"created"`
Updated time.Time `json:"updated"`
}
因此,当我使用 CQL 时,主要所有函数查询都根据 ID 进行过滤,但在一个查询中,我必须使用 DESC 中的“Status”上的 where 子句和“Created”排序,如下所示:
SELECT id, user_id, title, description, status, created, updated FROM todos WHERE status = ? ORDER BY created
目前我正在使用以下型号:
CREATE TABLE todos (
id UUID,
user_id TEXT,
title TEXT,
description TEXT,
status TEXT,
created TIMESTAMP,
updated TIMESTAMP,
PRIMARY KEY((status, created), id)
);
但是使用这个我遇到了过滤错误。完美的表创建应该是什么,这样我就可以毫无问题地执行所需的操作
期待一些好的回应来解决我的问题
过滤错误是因为分区键是状态和创建这两个值的复合键。因此,从分区的角度来看,它们被散列为单个值。通过仅提供密钥的 1 部分,它将被迫扫描所有分区。
您的最初反应是将主键更改为:
PRIMARY KEY((status), created, id)
双括号不是必需的,但我保留它们是为了让变化显而易见。不过,状态的基数值很可能非常低,这会导致单个分区内的记录数量非常多 - 这是不可取的。
您可能会想使用二级索引 - 但这会遇到同样的问题(物化视图也是如此)。基数问题需要解决。
我希望以某种形式使用时间桶,例如:
PRIMARY KEY((status, time_bucket), created, id)
其中 time_bucket 是时间戳字段,它是应用程序提供的已创建字段的截断版本,例如周、天甚至小时。您应该知道要在哪个时间段内搜索,或者要并行搜索的多个时间段,并在应用程序代码中构建最终的有序答案。要使用的截断级别应基于您期望在一段时间内每个状态的数据量。
这增加了分区键的基数并将其分布在集群内的节点上。
如果没有更新,TWCS 将是一个可行的选择,但结构中更新字段的存在表明情况并非如此。