34

I have to work with a column family that has (user_id, timestamp) as key. In my query I would like to fetch all records in a given time range independent of the user_id. This is the exact table schema:

CREATE TABLE userlog (
  user_id text,
  ts timestamp,
  action text,
  app_type text,
  channel_name text,
  channel_session_id text,
  pid text,
  region_id text,
  PRIMARY KEY (user_id, ts)
)

I tried to run

SELECT * FROM userlog  WHERE ts >= '2013-01-01 00:00:00+0200' AND  ts <= '2013-08-13 23:59:00+0200' ALLOW FILTERING;

which works fine on my local cassandra installation containing a small data set but fails with

Request did not complete within rpc_timeout.

on the productive system containing all the data.

Is there a, preferably cql, query that runs smoothly with the given column family or de we have to change the design?

4

3 回答 3

38

超时是因为 Cassandra 返回数据的时间超过了超时时间(默认为 10 秒)。对于您的查询,Cassandra 将在返回之前尝试获取整个数据集。对于多于几条记录,这很容易比超时时间更长。

对于产生大量数据的查询,您需要分页,例如

SELECT * FROM userlog WHERE ts >= '2013-01-01 00:00:00+0200' AND  ts <= '2013-08-13 23:59:00+0200' AND token(user_id) > previous_token LIMIT 100 ALLOW FILTERING;

user_id返回的前一个 user_id在哪里。您还需要在 ts 上进行分页,以保证您获得最后返回的 user_id 的所有记录。

或者,在 Cassandra 2.0.0(刚刚发布)中,分页是透明地完成的,因此您的原始查询应该可以在没有超时或手动分页的情况下工作。

ALLOW FILTERING意味着 Cassandra 正在读取您的所有数据,但仅返回指定范围内的数据。这仅在范围是大部分数据时才有效。如果您想在例如 5 分钟的时间窗口内查找记录,这将是非常低效的。

于 2013-09-09T12:36:15.187 回答
7

看来能够按时间(或任何范围)查询的热点是将一些“其他列”指定为您的分区键,然后将时间戳指定为“集群列

CREATE TABLE postsbyuser (
     userid bigint,
     posttime timestamp,
     postid uuid,
     postcontent text,
     PRIMARY KEY ((userid), posttime)
   ) WITH CLUSTERING ORDER BY (posttime DESC);

插入虚假数据

  insert into postsbyuser (userid, posttime) values (77, '2013-04-03 07:04:00');

和查询(重要的部分是它是一个“快速”查询并且ALLOW FILTERING不是必需的,它应该是这样的):

  SELECT * FROM postsbyuser where userid=77 and posttime > '2013-04-03 07:03:00' and posttime < '2013-04-03 08:04:00';

您还可以使用技巧按天分组(因此能够按天查询)或不分组。

如果您使用“按天分组”风格的技巧,那么二级索引也是一种选择(尽管二级索引似乎只适用于“EQ”=运算符?)。

于 2018-02-12T20:38:04.823 回答
1

一般来说,这可能表明您没有对架构进行建模以适应您的数据查询,这是 Cassandra 的处理方式(https://docs.datastax.com/en/cql/3.3/cql/ddl /dataModelingApproach.html )...

因此,理想情况下,您应该对架构进行建模以适应查询。有一些关于如何为 Cassandra 进行时间序列建模的资源,尽管例如这个幻灯片共享似乎与你所拥有的相似 - 但它不是对你想要做的那种查询的广告支持。我认为我实际上没有找到支持“获取特定时间范围内的所有数据”查询的 Cassandra 模式示例。

在任何情况下,对于这个答案的其余部分,我会假设你被你为这个迭代所拥有的模式所困。

您可以通过两个查询来执行此操作:

SELECT DISTINCT user_id FROM userlog;

然后,对于每个用户,

SELECT * FROM userlog WHERE
  user_id='<user>'
  AND ts >= '2013-01-01 00:00:00+0200'
  AND ts <= '2013-08-13 23:59:00+0200';

如果用户 ID 的集合是中小型的,您可以使用IN查询来侥幸:

SELECT * FROM userlog WHERE
  user_id IN ('sampleuser', 'sampleadmin', ...)
  AND ts >= '2013-01-01 00:00:00+0200'
  AND ts <= '2013-08-13 23:59:00+0200';

请注意,这在没有 ALLOW FILTERING.

于 2018-11-06T12:29:05.983 回答