假设我有一个具有以下结构的表
create table tasks (
user_id uuid,
name text,
task_id uuid,
description text,
primary key ((user_id), name, task_id)
);
它允许我为用户按name
升序排序所有任务。我还将task_id
添加到主键以避免upserts。以下查询成立
select * from tasks where user_id = ?
以及
select * from tasks where user_id = ? and name > ?
但是,我无法完成特定task_id
的任务。例如,以下查询崩溃
select * from tasks where user_id = ? and task_id = ?
有这个错误
PRIMARY KEY column "task_id" cannot be restricted as preceding column "name" is not restricted
它需要指定name
列,但目前我只有task_id
(例如来自网址)和user_id
(来自会话)。
我应该如何创建此表来执行这两个查询?或者我需要为第二种情况创建单独的表?这种情况下的常见模式是什么?
答案 0 :(得分:1)
您只需添加一个与task_id具有相同值的冗余列taskId,并在taskId上创建二级索引。
然后,您可以查询user_id=? and tsakId=?
答案 1 :(得分:0)
PRIMARY KEY column "task_id" cannot be restricted as preceding
column "name" is not restricted
您看到此错误,因为CQL不允许查询跳过主键组件。
我应该如何创建此表来执行这两个查询?或者我需要为第二种情况创建单独的表?这种情况下的常见模式是什么?
正如您所怀疑的那样,使用Cassandra解决此类问题的典型方法是为每个查询创建一个附加表。在这种情况下,使用PRIMARY KEY重新创建表以匹配您的其他查询模式将只是这样:
create table tasks_by_user_and_task (
user_id uuid,
name text,
task_id uuid,
description text,
primary key ((user_id), task_id)
);
您只需添加一个与task_id具有相同值的冗余列taskId,并在taskId上创建二级索引。
虽然我通常不喜欢使用二级索引,但在这种情况下可能执行正常。原因是,您仍然会通过分区键限制查询,这将消除检查其他节点的需要。缺点(如Undefined_variable所指出的)是您无法在主键组件上创建辅助索引,因此您需要复制该列(并将索引应用于非主键列)以使该解决方案起作用。
对两种性能解决方案进行建模和测试可能是一个好主意。
答案 2 :(得分:0)
如果您有额外的磁盘空间,最好的方法是在第二个表中复制数据。您应该避免在生产中使用二级索引。当然,您的应用程序需要写入这两个表。但是卡桑德拉很擅长提高效率。
create table tasks_by_name (
user_id uuid,
name text,
task_id uuid,
description text,
primary key ((user_id), name, task_id)
);
create table tasks_by_id (
user_id uuid,
name text,
task_id uuid,
description text,
primary key ((user_id), task_id)
);