我需要运行以下类型的查询:
SELECT * FROM outbox
ORDER BY timestamp ASC
LIMIT 10
DDL:
CREATE TABLE IF NOT EXISTS stories_views.outbox (
key_id uuid,
message text,
created_at timestamp,
PRIMARY KEY ((key_id), created_at))
WITH CLUSTERING ORDER BY (created_at asc)
AND compaction = { 'class' : 'SizeTieredCompactionStrategy' };
请告诉我如何设计一个表,这样就不会在整个 Cassandra 集群中进行搜索。
如果您的查询始终是您上面描述的内容,那么您的方法是正确的。如果您的查询设计不当,Cassandra® 作为分布式 NoSQL 数据库将执行完整集群扫描。如果您正在利用点查询,即利用完整的主键,它不会进行扫描。在
5.x
及更高版本中,我们现在拥有高效的存储附加索引 (SAI),它将帮助您灵活地通过表上的非主键列进行查询。
为了更多地了解数据建模,您可以利用这个基于免费浏览器的便捷教程,您可以在其中了解数据建模的细微差别。干杯!
如果您使用限制,则不一定会读取整个表,但整个集群将执行一些工作,因为您也没有指定分区 - 即应用程序连接到的数据中心中的所有副本都将扫描本地表中的数据,直到满足 10 个结果或完全扫描表。
这在 Cassandra 中被认为是反模式,因为它违背了数据分区的目的。如果要实现可扩展的读取,就需要按分区查询。这将确保不超过 3 个节点(假设复制因子为 3)必须扫描其数据的子集。
在这种情况下,可扩展查询可能如下所示:
SELECT * FROM stories_views.outbox WHERE key_id = foo ORDER BY created_at ASC LIMIT 10;
这将返回带有 key_id“foo”的分区的最早 10 个结果。
如果应用程序确实需要扫描表中的所有 key_id 条目,那么最好的(尽管不是很好)选择可能是非规范化并创建一个新表,其中时间窗口存储桶作为分区(例如代表一小时、一个小时的分区)天、一周等),然后扫描存储桶,直到获得所需的结果数量。
第一个挑战是调整存储桶的大小,以免构建巨大的分区(100MB 或以上)。
这种方法的第二个问题是,划分时间窗口也是一种反模式,会妨碍平衡工作负载分配。对于表示当前时间窗口的分区,高峰时段的高吞吐量需求可能会使一小部分节点因写入请求(也可能是读取)而过载。