CQL 查询按字段排序的整个表/视图的唯一方法是使分区键保持不变。恰好一台机器(乘以复制因子)将保存整个表。例如。使用始终为零的 partition INT 分区键和作为需要排序的字段的集群键。即使集群中有更多节点,您也应该观察到类似于在排序字段上有索引的单节点数据库的读/写/容量性能。这并没有完全违背 Cassandra 的目的,因为它可以帮助将来扩展。
如果性能不足,您可以决定通过增加分区种类来进行扩展。例如。当使用 4 个节点时,从 0、1、2、3 中随机选择插入将高达四倍的读/写/容量性能。然后要找到“10 个最近的”项目,您必须手动查询所有 4 个分区并对结果进行合并排序。
理论上,Cassandra 可以为 INSERT 提供动态 node-count-max-modulo 分区键,为 SELECT 提供合并排序(ALLOW FILTERING)。
Cassandra 的设计目标不允许全局排序
要允许写入、读取和存储容量随节点数线性扩展,Cassandra 需要:
- 每个插入都位于一个节点上。
- 每个选择都位于一个节点上。
- 客户端在所有节点之间以类似方式分配工作负载。
如果我理解正确,结果是全表单字段排序查询将始终需要从整个集群中读取并合并排序。
注意物化视图等同于表格,它们没有任何神奇的属性使它们更擅长全局排序。请参阅http://www.datastax.com/dev/blog/we-shall-have-order,其中 Aaron Ploetz 同意 cassandra 和 cql 无法在没有分区和规模的情况下对一个字段进行排序。
示例解决方案
CREATE KEYSPACE IF NOT EXISTS
tmpsort
WITH REPLICATION =
{'class':'SimpleStrategy', 'replication_factor' : 1};
USE tmpsort;
CREATE TABLE record_ids (
partition int,
last_modified_date timestamp,
record_id int,
PRIMARY KEY((partition), last_modified_date, record_id))
WITH CLUSTERING ORDER BY (last_modified_date DESC);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 1, DATEOF(NOW()), 100);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 2, DATEOF(NOW()), 101);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 3, DATEOF(NOW()), 102);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 1, DATEOF(NOW()), 103);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 2, DATEOF(NOW()), 104);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 3, DATEOF(NOW()), 105);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 3, DATEOF(NOW()), 106);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 3, DATEOF(NOW()), 107);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 2, DATEOF(NOW()), 108);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 3, DATEOF(NOW()), 109);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 1, DATEOF(NOW()), 110);
INSERT INTO record_ids (partition, last_modified_date, record_id) VALUES ( 1, DATEOF(NOW()), 111);
SELECT * FROM record_ids;
-- Note the results are only sorted in their partition
-- To try again:
-- DROP KEYSPACE tmpsort;
请注意,如果没有 WHERE 子句,您将获得令牌(分区键)顺序的结果。见https://dba.stackexchange.com/questions/157537/querying-cassandra-without-a-partition-key
其他数据库分布模型
如果我理解正确 - CockroachDB 在任何给定时间将单调递增数据到一个节点时类似地瓶颈读/写性能,但存储容量将线性扩展。此外,其他范围查询,如“最旧的 10”或“在日期 X 和日期 Y 之间”,会将负载分布在更多节点上,而不是 Cassandra。这是因为 CockroachDB 的数据库是一个巨大的排序键值存储,每当排序数据范围达到一定大小时,它就会重新分配。