web-dev-qa-db-ja.com

cassandra時間範囲内のすべてのレコードを取得

キーとして(user_id、timestamp)を持つカラムファミリを使用する必要があります。私のクエリでは、user_idに関係なく、指定された時間範囲内のすべてのレコードを取得します。これは正確なテーブルスキーマです。

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)
)

走ってみた

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

これは、ローカルのcassandra小さなデータセットを含むインストールで正常に動作しますが、

Request did not complete within rpc_timeout.

すべてのデータを含む本稼動システム上。

与えられた列ファミリでスムーズに実行される、できればcqlクエリがありますか、それとも設計を変更する必要がありますか?

26
Faber

タイムアウトは、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です。また、最後に返されたuser_idのすべてのレコードを確実に取得するために、tsをページングする必要があります。

または、Cassandra 2.0.0(リリース直後))では、ページングは​​透過的に行われるため、タイムアウトや手動ページングなしで元のクエリが機能します。

ALLOW FILTERINGは、Cassandraはすべてのデータを読み取りますが、指定された範囲内のデータのみを返します。これは、範囲がデータのほとんどである場合にのみ効率的です。 5分の時間枠では、これは非常に非効率的です。

33
Richard

hotness は、時間(または任意の範囲)で照会できるため、パーティションキーとして「その他の列」を指定し、次に「クラスタリング列」としてタイムスタンプを指定するように見えます

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」でのみ機能するようです=演算子?)。

3
rogerdpack

一般に、これは、データクエリに合わせてスキーマをモデル化していないことを示している可能性があります。これは、Cassandra物事の実行方法です( https:// docs。 datastax.com/en/cql/3.3/cql/ddl/dataModelingApproach.html )...

そのため、理想的には、クエリに合わせてスキーマをモデル化します。 Cassandraの時系列モデリングを行う方法に関するリソースがいくつかありますが、 このスライド共有 は、あなたが持っているものと似ているように見えます-しかし、それはあなたがしたい種類のクエリに対する広告のサポートではありません。 「特定の時間範囲のすべてのデータを取得する」クエリをサポートするCassandra=スキーマの例を実際に見つけたとは思わない。

いずれにせよ、この回答の残りの部分では、この反復で得たスキーマに固執していると仮定します。

これは2つのクエリとして実行できます。

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';

これが機能することに注意してくださいwithoutALLOW FILTERING

0
m01