为什么Cassandra建议不要在高基数列上创建索引?


10

Cassandra文档指出,

在以下情况下不要使用索引:

  • 在高基数列上,因为您随后查询了大量记录以获取少量结果。请参阅下面的使用高基数列索引的问题。

继续

如果在高基数列上创建索引,该索引具有许多不同的值,则字段之间的查询将导致许多查找,结果很少。在拥有十亿首歌曲的表中,按作者(通常是每首歌曲唯一的值)而不是按艺术家查找歌曲的效率很低。手动将表维护为索引形式而不是使用Cassandra内置索引可能会更有效。对于包含唯一数据的列,有时为了方便起见,最好使用索引,只要对具有索引列的表的查询量适中且不在恒定负载下即可。

但是从来没有真正回答这个问题:为什么效率低下?我不知道“手动将表作为索引的一种形式”是什么意思。但是,这却与“………有时为了方便起见,只要查询量适中,使用索引有时是很好的性能……”。

这是否只是在告诉我在何时何地可以使用PK?什么是效率低下?我的理解是,要查询索引的查询将需要查询集群中的每个¹节点,然后每个节点都将在其本地索引中进行查找,然后将结果汇总。除了我们要付出网络等待时间之外,这并不一定是昂贵的(每个索引查找都应该相当便宜),因为我们必须等待最慢的节点。我在这里想念什么吗?

但是,如果我有一个包含不计其数的项目的收藏集,那么在极少数情况下,需要通过一个不同但几乎独特的属性来查找……这是一种适当的用法,对吗?

¹每个?IDK,如果复制意味着复制因子为3时,它可以达到群集的1/3?

Answers:


6

使用Cassandra索引(与主键相对的“辅助索引”),每个节点都必须查询自己的本地数据以响应查询(请参见Cassandra 辅助索引exes FAQ)。这些索引也是使用后台过程构建的。这种背景意味着索引可能在命中方面返回假阴性(或在未命中方面返回假阳性)。

这意味着在高基数列中,该列的变化率(增加/删除)可能非常高。因此,如果该变化率比通过后台进程更新索引,那么使用索引是“低效的”(索引执行的工作量超过了应用程序所需的工作量,这通常可能会得到错误的答案) 。

就查询准确性而言,一种更有效的方法可能是维护第二个不是第二个索引。与索引相反,表的处理方式与其他任何表一样。它们更有可能为您的应用程序提供预期的查询结果。缺点是现在将表保留为索引,而不是Cassandra的“二级索引”成为应用程序约束(即,您的应用程序代码现在必须知道要从该“索引”表中插入/删除行,并且 通过应用程序级别的“对帐”使两个表保持同步)。

希望这可以帮助!


使用后台进程构建索引有点……丑陋。我想用户会看到误报吗?(我看不出它们不会如此。)我仍然要问的唯一问题是您在哪里说:“这意味着在高基数列中,该列的变化率(即增加/删除)可以很高。” —我知道为什么相对于bg索引建立的变化率会不好,但是我仍然不知道高基数与它有什么关系。(当然,即使是低基数的列也会遭受同样的命运,不是吗?)
Thanatos,

是的,低基数列将遭受同样的命运。我承认我的想法有点模糊。我假定一个高基数指数将是更可能有变化(因而更容易表现出假阳性/阴性结果)的更高的速率; 最相关的是变化率(相对于背景索引编制过程),而不是基数。
卡斯塔利亚

2

一些术语:父表是在其上创建索引的表。二级索引表是为了维护另一个表上的索引而创建的表。

二级索引表的数据与父表的数据存储在同一节点上。Cassandra分区器不会分区和分发索引表数据。因此,如果要在索引列上执行查找,将查询所有节点,而不仅仅是包含数据的副本节点。(协调器节点不知道数据位于何处)https://www.datastax.com/dev/blog/cassandra-native-secondary-index-deep-dive

对于诸如ssn或其他唯一ID之类的高基数列,将使用主键进行一对一映射。如果在此类列上创建索引,则数据驻留在节点的复制因子数上,但是在所有节点上执行查找调用。最好的情况是,协调器直接命中包含数据的节点,一旦达到一致性级别,您就可以得到结果。最糟糕的是,如果索引中没有您要查找的数据,您将等到所有节点都响应后才发现该数据不存在。因此,对于二级索引表上的每个查找调用,所有节点都会被命中。如果该表是普通的C *表,则将其与每个查找调用仅命中的节点的复制因子数进行比较。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.