假设我有一个列族:
CREATE TABLE update_audit (
scopeid bigint,
formid bigint,
time timestamp,
record_link_id bigint,
ipaddress text,
user_zuid bigint,
value text,
PRIMARY KEY ((scopeid, formid), time)
) WITH CLUSTERING ORDER BY (time DESC)
使用两个辅助索引,其中 record_link_id
是高基数列:
CREATE INDEX update_audit_id_idx ON update_audit (record_link_id);
CREATE INDEX update_audit_user_zuid_idx ON update_audit (user_zuid);
根据我的知识,Cassandra将创建两个隐藏列系列,如下所示:
CREATE TABLE update_audit_id_idx(
record_link_id bigint,
scopeid bigint,
formid bigint,
time timestamp
PRIMARY KEY ((record_link_id), scopeid, formid, time)
);
CREATE TABLE update_audit_user_zuid_idx(
user_zuid bigint,
scopeid bigint,
formid bigint,
time timestamp
PRIMARY KEY ((user_zuid), scopeid, formid, time)
);
Cassandra二级索引实现为本地索引,而不是像普通表一样分发 . 每个节点仅存储其存储的数据的索引 .
请考虑以下查询:
select * from update_audit where scopeid=35 and formid=78005 and record_link_id=9897;
-
这个查询如何在Cassandra中执行'under the hood'?
-
高基数列索引(
record_link_id
)将如何影响其性能? -
Cassandra会触摸上述查询的所有节点吗?为什么?
-
首先执行哪个条件,基表partition_key或二级索引partition_key? Cassandra 将如何与这两个结果相交?
2 回答
基本上,将返回分区
scopeid=35
和formid=78005
的所有数据,然后通过record_link_id
索引进行过滤 . 它将查找9897
的record_link_id
条目,并尝试匹配与scopeid=35
和formid=78005
返回的行匹配的条目 . 将返回分区键和索引键的行的交集 .高基数索引实质上为(几乎)主表中的每个条目创建一行 . 性能受到影响,因为Cassandra旨在对查询结果执行顺序读取 . 索引查询实质上迫使Cassandra执行随机读取 . 随着索引值的基数增加,查找查询值所需的时间也会增加 .
不可以 . 它应该只触及负责
scopeid=35
和formid=78005
分区的节点 . 索引同样存储在本地,仅包含对本地节点有效的条目 .这里的问题是方法不能扩展,如果
update_audit
是一个大型数据集,它将会很慢 . MVP Richard Low有一篇关于二级索引(The Sweet Spot For Cassandra Secondary Indexing)的精彩文章,特别是关于这一点:现在,您首先通过特定分区限制的方法将有所帮助(因为您的分区当然应该适合内存) . 但我觉得这里表现更好的选择是使
record_link_id
成为集群密钥,而不是依赖于二级索引 .Edit
这取决于行的宽度 . 关于极低基数索引的棘手问题是,返回的行的百分比通常更大 . 例如,考虑一个宽行
users
表 . 您在查询中按分区键限制,但仍返回10,000行 . 如果您的索引类似于gender
,那么您的查询将必须过滤掉这些行中的大约一半,这些行将无法正常执行 .二级索引往往效果最好(缺乏更好的描述)"middle of the road"基数 . 使用上述宽行
users
表的示例,country
或state
上的索引应该比gender
上的索引执行得更好(假设大多数用户并非都生活在同一个国家或州) .Edit 20180913
请考虑以下图表,取自Java Driver documentation(v3.6):
基本上,分页将导致查询自行分解并返回到集群以进行下一次结果迭代 . 它不太可能超时,但性能将呈下降趋势,与总结果集的大小和集群中的节点数成比例 .
TL; DR;请求的结果越多,节点越多,时间越长它需要 .
在Cassandra 2.x中也可以仅使用二级索引进行查询
但这对获取数据有很大影响,因为它会读取分布式环境中的所有分区 . 此查询提取的数据也不一致,无法在其上进行中继 .
Suggestion:
使用辅助索引被认为是NoSQL数据模型视图中的DIRT查询 .
为了避免二级索引,我们可以创建一个新表并将数据复制到它 . 由于这是应用程序的查询,因此表是从查询派生的 .