首页 > 解决方案 > 关于 Cassandra 关于键、分区的文档(草率,仍然令人困惑)

问题描述

我有一个高写入表,我要从 Oracle 转移到 Cassandra。在 Oracle 中,PK 是一个(int:clientId,id:UUID)。大约有 100 亿行。我马上就遇到了这个荒谬的警告:

https://docs.datastax.com/en/cql/3.3/cql/cql_using/useWhenIndex.html:“如果您在具有许多不同值的高基数列上创建索引,则会在字段之间产生查询许多人只寻求很少的结果。在有十亿首歌曲的表中,按作者(每首歌曲通常唯一的值)而不是他们的艺术家来查找歌曲可能非常低效。它可能会更有效率手动将表维护为一种索引形式,而不是使用 Cassandra 内置索引。”

这似乎不仅破坏了 PK 的有效查找,它还没有定义“在字段之间查询”的含义以及内置索引、二级索引和主键+集群子短语之间的区别创建表命令。垃圾描述。这是 2019 年。现在不应该解决这个问题吗?

AFAIK 无论如何都是误导性的:

CREATE TABLE dev.record (
clientid int,
id uuid,
version int,
payload text,
PRIMARY KEY (clientid, id, version)
) WITH CLUSTERING ORDER BY (id ASC, version DESC)

insert into record (id,version,clientid,payload) values
(d5ca94dd-1001-4c51-9854-554256a5b9f9,3,1001,'');
insert into record (id,version,clientid,payload) values
(d5ca94dd-1002-4c51-9854-554256a5b9e5,0,1002,'');

clientid 上的令牌确实显示它们按预期位于不同的分区中。

谈到重点。如果在给定 clientId 的情况下寻找单行,并且 UUID ---AND--- Cassandra 允许您跳过指定 clientId 以便它不知道要搜索哪个节点,那么请确保查找可能很慢. 但它没有:

select * from record where id=
  d5ca94dd-1002-4c51-9854-554256a5b9e5;
InvalidRequest: ... despite the performance unpredictability,
use ALLOW FILTERING"

其他不包括 clientid 的变体也是如此。所以我们不应该得出结论 Cassandra 处理返回“很少结果”的高基数表搜索就可以了吗?

标签: cassandra

解决方案


任何需要读取数据库的整个上下文的东西都不会起作用,扫描就是这种情况,id因为您的任何clientid分区键都可能包含一个。遍历每个主机可能有数千个 sstable 并遍历每个分区的每个分区进行检查是行不通的。如果在使用数据模型时遇到困难并且没有完全了解分区键和集群键之间的差异,我建议您在设计架构之前先浏览一些介绍课程(即 datastax 学院)、youtube 视频或书籍等。这不是一个关系数据库,围绕您的数据而不是您的查询进行设计会给您带来麻烦。从 oracle 迁移时,您不应该只是复制表并移动数据,否则它将无法正常工作。

集群键是分区数据在磁盘上的排序顺序,这就是它所指的“内置索引”。每个 sstable 都有一个索引组件,其中包含该 sstable 的分区键位置。这还包括每 64kb(至少默认情况下)可以搜索的每个分区的集群键索引。每个索引点之间存在的聚类键是未知的,因此必须检查它们。很久以前,还保留了一个集群键的布隆过滤器,但它是一个非常罕见的用例,与 2.0 中删除的开销相比,它有所帮助。

二级索引很难很好地扩展,这是关于基数的警告的来源,我强烈建议只对数据进行非规范化,不要以任何形式使用索引,因为在分布式系统中使用大型分散聚集查询将会产生可用性和性能问题。如果您真的需要它,请查看http://www.doanduyhai.com/blog/?p=13191以尝试正确获取数据(我认为不值得)。


推荐阅读