卡桑德拉允许过滤,但需要谨慎使用。

14

我有一个如下的表格

CREATE TABLE test (
 day int,
 id varchar,  
 start int,
 action varchar,  
 PRIMARY KEY((day),start,id)
);

我想运行这个查询

Select * from test where day=1 and start > 1475485412 and start < 1485785654 
and action='accept' ALLOW FILTERING

使用ALLOW FILTERING是否高效?

我期望Cassandra按照以下顺序进行过滤

1. By Partitioning column(day)
2. By the range column(start) on the 1's result
3. By action column on 2's result. 

因此,在此查询中使用allow filtering不会是一个坏选择。

如果在where子句上有多个过滤参数,并且非索引列是最后一个,过滤器将如何工作?请解释。


这段视频来自DataStax Academy,对于这个主题非常有帮助。 - RyanQuey
2个回答

7
这个 "ALLOW FILTERING" 查询有效吗?
当你说 "this" 的时候,你指的是在查询和模型的上下文中,然而,一个 ALLOW FILTERING 查询的效率主要取决于它需要过滤的数据。除非你展示一些真实数据,否则这是一个难以回答的问题。
我期望cassandra将按照以下顺序过滤...
是的,这就是会发生的事情。然而,在查询中包含 ALLOW FILTERING 子句通常意味着表设计不佳,也就是说,你没有遵循 Cassandra 建模的一些指导方针(特别是 "一个查询 <--> 一个表")。
作为解决方案,我可以提示你将 "action" 字段包含在聚簇键中,紧接在 "start" 字段之前,修改你的表定义:
CREATE TABLE test (
 day int,
 id varchar,  
 start int,
 action varchar,  
 PRIMARY KEY((day),action,start,id)
);

然后,您需要重新编写查询,不使用任何ALLOW FILTERING子句:

SELECT * FROM test WHERE day=1 AND action='accept' AND start > 1475485412 AND start < 1485785654

只存在一个小问题,即如果一个记录“切换”了 action 值,则无法对单个 action 字段执行更新(因为它现在是聚簇键的一部分),因此需要使用旧的 action 值执行删除并插入正确的新值。但是,如果您拥有Cassandra 3.0+,则可以通过新的Materialized View实现完成所有这些操作。有关更多信息,请查看文档


如果查询按照我所说的顺序扫描磁盘,那么允许过滤不是一个坏选择,对吧。因为它只过滤了有限数量的数据。 - Bharathi
@Bharathi: 你也想扫描墓碑吗?我们对你的数据一无所知,所以一般的建议是“不要使用ALLOW FILTERING”,但如果你认为你只有一小批记录,那就尽管使用它。毕竟,在Cassandra中使用头脑绝对是最好的建模方式... - xmas79
2
我只是想了解ALLOW FILTERING。我的用例并不完全与我在这里陈述的相同,我不能公开地将其放在这里。我想知道如果Cassandra按照我所述的顺序进行过滤,那么它要扫描的数据量就不会有任何担忧。 - Bharathi
@xmas79 有没有办法避免扫描墓碑? - soote
1
@soote,唯一的方法就是避免删除,只扫描实时数据。如果您想要“跳过”不必要的数据,那么请更改您的模型并使您的查询更加高效。如果您无法这样做(两者都不能),那么请等待压缩... - xmas79

2

通常情况下,ALLOW FILTERING不是高效的。

但最终取决于您正在获取的数据量(对于这些数据,Cassandra必须使用ALLOW FILTERING)以及正在获取数据的大小。

在您的情况下,Cassandra无需过滤即可达到以下要求:

  1. 通过1的结果列(开始)的范围列

正如您所提到的一样。但在那之后,它将依赖于查询本身中允许搜索数据的过滤器。

现在,请记住以下内容:

如果您的表包含例如100万行数据,并且其中95%的数据都具有请求的值,则查询仍然会相对高效,您应该使用ALLOW FILTERING。

另一方面,如果您的表包含了100万行数据,只有2行包含请求的值,则查询非常低效。Cassandra将无故加载999,998行数据。如果此查询经常使用,则最好在time1列上添加索引。

因此,请确保首先考虑以上内容。如果适用于您的情况,请使用FILTERING。 否则,在“action”上添加二级索引可能更明智。

PS:进行了一些小的编辑。


1
我在不同的问题上读到了相同的答案。这不是这个问题的答案。如果您知道,请具体说明查询将如何工作。 - Bharathi
我不知道那个问题的答案,但我在这篇旧的Datastax文档中读到了这篇文章。请阅读一下。尽管我仍然认为我的回答也很好地解释了它。但如果您发现其他情况,请在这里提出。这也可以消除我的误解(如果有的话)。谢谢! - r005t3r
1
谢谢更新。我知道ALLOW FILTERING将扫描整个列族。但问题在于,如果where子句上有多个过滤参数,并且未索引的列是最后一个,过滤器会如何工作?请阅读问题并告诉我是否需要进行任何编辑以获得更好的理解。 - Bharathi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接