【发布时间】:2024-01-19 11:46:01
【问题描述】:
我想存储一个 ID 和一个日期,我想检索从 dateA 到 dateB 的所有条目,我究竟需要什么才能执行select from my_column_family where date >= dateA and date < dateB;?
【问题讨论】:
-
顺便说一句,这没有答案:*.com/questions/3535017/…(无论如何它都是旧版本的)
我想存储一个 ID 和一个日期,我想检索从 dateA 到 dateB 的所有条目,我究竟需要什么才能执行select from my_column_family where date >= dateA and date < dateB;?
【问题讨论】:
#cassandra (IRC) 的人帮我找到了一个方法,有很多微妙的细节,所以我想在这里记录一下。
首先你需要声明一个与此类似的列族(来自 cassandra-cli 的示例):
create column family users with comparator=UTF8Type and key_validation_class=UTF8Type and column_metadata=[
{column_name: id, validation_class: LongType}
{column_name: name, validation_class: UTF8Type, index_type: KEYS}
{column_name: age, validation_class: LongType}
];
关于此声明的一些重要事项:
现在让我们添加一些值:
set users[1][name] = john;
set users[1][age] = 19;
set users[2][name] = jane;
set users[2][age] = 21;
set users[3][name] = john;
set users[3][age] = 32;
据此:http://pkghosh.wordpress.com/2011/03/02/cassandra-secondary-index-patterns/ Cassandra 不支持 < 运算符,它所做的是手动排除不匹配的行,但它会在有结果集之后这样做并且它也拒绝这样做,除非并进行了实际过滤。
这意味着像get users where age > 20; 这样的查询将返回null,但如果我们添加一个包含= 的谓词,它就会神奇地起作用。
这里是二级索引很重要的地方,没有它你不能使用= 所以在这个例子中我可以使用get users where name = jane; 但我不能要求get users where age = 21;
有趣的是,在使用= 之后,< 可以正常工作,因此拥有二级索引可以让您请求get users where name = john and age > 20;,它会正确过滤。
【讨论】:
有几种方法可以解决这个问题。最简单的可能是您自己的答案中提到的具有相等限制的二级索引解决方案。我使用了这种方法,添加了一个名为 'valid' 的附加列,将值设置为 1。然后查询可以变为 where valid=1 and date>nnnn
其他解决方案需要额外的列族和额外的查询。
在加载数据时,创建并添加一个包含时间戳作为键的列族,每个条目都会列出所有用户 ID 作为列名。
如果分区策略是有序的,那么单个RangeSliceQuery可以将日期范围指定为键范围,并获取每个键的所有列。然后遍历结果键,使用每个用户 ID 的列值,如果需要,查询原始列族以获取与每个 ID 关联的数据。 Cassandra 总是按顺序存储列名,读取时可以颠倒。
但是,正如documented,有序分区器并不理想,导致热点和节点负载均衡困难。
如果没有有序的分区程序,仍然保留时间戳列族,您将不得不在加载数据时创建另一个列族,您可以将所有时间戳存储为一个或多个已知键下的列(例如“创建”或“更新” ')。第一个查询将是一个已知键的 SliceQuery,然后列名(作为时间戳)将提供 MultigetSliceQuery 的键em> 到时间戳列族。
我对此使用了变体,通常添加复合键或列以增加灵活性。
【讨论】: