假设我有一个列族:
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;
record_link_id
)如何影响其性能?答案 0 :(得分:45)
select * from update_audit where scopeid=35 and formid=78005 and record_link_id=9897;
上述查询如何在cassandra中内部工作?
基本上,将返回分区scopeid=35
和formid=78005
的所有数据,然后通过record_link_id
索引进行过滤。它将查找record_link_id
的{{1}}条目,并尝试匹配与9897
和scopeid=35
返回的行匹配的条目。将返回分区键和索引键的行的交集。
高基数列(record_link_id)索引如何影响上述查询的查询性能?
高基数索引实质上为(几乎)主表中的每个条目创建一行。性能受到影响,因为Cassandra旨在对查询结果执行顺序读取。索引查询实质上迫使Cassandra执行随机读取。随着索引值的基数增加,查找查询值所需的时间也会增加。
cassandra会触及上述查询的所有节点吗?为什么?
没有。它应该只触及负责formid=78005
和scopeid=35
分区的节点。索引同样存储在本地,仅包含对本地节点有效的条目。
在高基数列上创建索引将是最快且最好的数据模型
这里的问题是方法不能扩展,如果formid=78005
是一个大型数据集,则方法会很慢。 MVP Richard Low有一篇关于二级索引(The Sweet Spot For Cassandra Secondary Indexing)的精彩文章,特别是关于这一点:
如果你的表明显大于内存,那么即使只返回几千个结果,查询也会非常慢。尽管看起来是一个有效的查询,但可能有数百万用户返回将是灾难性的。
...
实际上,这意味着索引对于返回数十或数百个结果非常有用。下次考虑使用二级索引时请记住这一点。
现在,您首先通过特定分区进行限制的方法将有所帮助(因为您的分区当然应该适合内存)。但我觉得这里表现更好的选择是让update_audit
成为一个集群密钥,而不是依赖于二级索引。
修改强>
即使我们提供主键,当有数百万用户扩展时,如何获得低基数索引的索引
这取决于行的宽度。关于极低基数索引的棘手问题是,返回的行的百分比通常更大。例如,考虑一个宽行record_link_id
表。您在查询中按分区键限制,但仍返回10,000行。如果您的索引类似于users
,那么您的查询必须过滤掉大约一半的行,这些行不会很好。
二级索引往往效果最好(缺乏更好的描述)“中间路线”基数。使用上面的宽行gender
表示例,users
或country
上的索引应该比state
上的索引执行得更好(假设大多数用户并非都生活在同一个国家或地区。)
修改20180913
对于第一个问题“上面的查询如何在cassandra中内部工作?”的答案,你知道使用分页查询时的行为是什么吗?
考虑以下图表,取自Java Driver documentation(v3.6):
基本上,分页将导致查询自行分解并返回到集群以进行下一次结果迭代。它不太可能超时,但性能会下降,与总结果集的大小和集群中的节点数成比例。
TL; DR;请求的结果越多,节点越多,所需的时间就越长。
答案 1 :(得分:2)
Cassandra 2.x
中也可以只使用二级索引进行查询从update_audit中选择*,其中record_link_id = 9897;
但这对获取数据有很大影响,因为它会读取分布式环境中的所有分区。此查询提取的数据也不一致,无法在其上进行中继。
<强>建议:强>
使用辅助索引被认为是NoSQL数据模型视图中的DIRT查询。
为了避免二级索引,我们可以创建一个新表并将数据复制到它。由于这是对应用程序的查询,因此表格来自查询。