web-dev-qa-db-ja.com

Cassandra cqlsh-タイムスタンプ列のマイクロ秒/ミリ秒を表示する方法?

タイムスタンプ列を含むCassandraテーブルに挿入しています。私が持っているデータはマイクロ秒精度であるため、時間データ文字列は次のようになります。

2015-02-16T18:00:03.234 + 00:

ただし、選択クエリを実行すると、cqlshでマイクロ秒データが表示されず、秒単位の精度までしか時間が表示されません。 234マイクロ秒のデータは表示されません。

2つの質問があると思います。

1)Cassandra=タイムスタンプデータ型でマイクロ秒をキャプチャしますか?私の推測はイエスですか?

2)cqlshで確認するにはどうすればよいですか?

テーブル定義:

create table data (
  datetime timestamp,
  id text,
  type text,
  data text,
  primary key (id, type, datetime)
) 
with compaction = {'class' : 'DateTieredCompactionStrategy'};

クエリの挿入Java PreparedStatment:

insert into data (datetime, id, type, data) values(?, ?, ?, ?);

選択クエリは単純でした:

select * from data;
21
WillZ

あなたの質問に答えるために、私はこれについて少し掘り下げました。

  1. Cassandra=タイムスタンプデータ型でマイクロ秒をキャプチャしますか?

マイクロ秒いいえ、ミリ秒はい。テーブルを作成し、行を挿入し、切り捨てられた時間までにクエリを実行しようとすると、機能しません。

_aploetz@cqlsh:stackoverflow> INSERT INTO data (datetime, id, type, data) 
VALUES ('2015-02-16T18:00:03.234+00:00','B26354','Blade Runner','Deckard- Filed and monitored.');
aploetz@cqlsh:stackoverflow> SELECT * FROM data 
WHERE id='B26354' AND type='Blade Runner' AND datetime='2015-02-16 12:00:03-0600';

 id | type | datetime | data
----+------+----------+------

(0 rows)
_

しかし、ミリ秒を指定して同じidtypeの値を照会すると:

_aploetz@cqlsh:stackoverflow> SELECT * FROM data 
WHERE id='B26354' AND type='Blade Runner' AND datetime='2015-02-16 12:00:03.234-0600';

 id     | type         | datetime                 | data
--------+--------------+--------------------------+-------------------------------
 B26354 | Blade Runner | 2015-02-16 12:00:03-0600 | Deckard- Filed and monitored.

(1 rows)
_

したがって、ミリ秒は間違いなくあります。この問題のために作成されたJIRAチケットがありました( CASSANDRA-587 )が、「修正しない」として解決されました。

  1. Cqlshで確認するにはどうすればよいですか?

ミリ秒が実際に存在することを実際に確認する1つの可能な方法は、次のようにtimestampAsBlob()関数内にblobAsBigint()関数をネストすることです。

_aploetz@cqlsh:stackoverflow> SELECT id, type, blobAsBigint(timestampAsBlob(datetime)), 
data FROM data;

 id     | type         | blobAsBigint(timestampAsBlob(datetime)) | data
--------+--------------+-----------------------------------------+-------------------------------
 B26354 | Blade Runner |                           1424109603234 | Deckard- Filed and monitored.

(1 rows)
_

最適ではありませんが、ここでは最後に「234」のミリ秒値を明確に見ることができます。これは、同じタイムスタンプの行を追加した場合に、ミリ秒なしでさらに明らかになります。

_aploetz@cqlsh:stackoverflow> INSERT INTO data (id, type, datetime, data)
VALUES ('B25881','Blade Runner','2015-02-16T18:00:03+00:00','Holden- Fine as long as nobody unplugs him.');
aploetz@cqlsh:stackoverflow> SELECT id, type, blobAsBigint(timestampAsBlob(datetime)), 
                 ...     data FROM data;

 id     | type         | blobAsBigint(timestampAsBlob(datetime)) | data
--------+--------------+-----------------------------------------+---------------------------------------------
 B25881 | Blade Runner |                           1424109603000 | Holden- Fine as long as nobody unplugs him.
 B26354 | Blade Runner |                           1424109603234 |               Deckard- Filed and monitored.

(2 rows)
_
46
Aaron

Pythonの 'strftime'構文を使用して、.cassandra/cqlshrcファイル内のdatetimeオブジェクトの 出力形式を設定 できます。

残念ながら、マイクロ秒の%fディレクティブ(ミリ秒のディレクティブではないようです) 機能しない 古いpythonバージョン、つまり、フォールバックする必要があることを意味しますblobAsBigint(timestampAsBlob(date))ソリューションへ。

7
Tom

「マイクロ秒」(例:03.234567)は「ミリ秒」(例:(03.234))を意味すると思います。

ここでの問題は、タイムスタンプの処理時に秒の小数部をサポートできなかったcqlshバグでした。

したがって、ミリ秒の値は実際の永続化レイヤー(cassandra)に保存されていますが、シェル(cqlsh)はそれらの表示に失敗しました。

これは、time_formatディレクティブを使用して小数秒を表示するように.cqlshrc%fを変更した場合でも当てはまります(例:%Y-%m-%d %H:%M:%S.%f%z)。この構成では、cqlshが秒の一部をロードせずにdatetimeオブジェクトをロードする方法に問題があるため、cqlshは3.234値に対して3.000000をレンダリングします。

とはいえ、この問題は CASSANDRA-10428 で修正され、 Cassandra 3.4 でリリースされました。

2
eprothro

Cassandraデータ型 'timestamp'を使用してマイクロ秒(100万分の1秒)を表示することは不可能です。そのデータ型で使用できる最大精度はミリ秒(1000分の1秒)であるためです。

http://docs.datastax.com/en/cql/3.1/cql/cql_reference/timestamp_type_r.html

タイムスタンプタイプの値は、エポックとして知られる標準のベースタイムからのミリ秒数を表す64ビット符号付き整数としてエンコードされます。

1
user892703

いくつかの関連コード:

cqlsh> CREATE KEYSPACE udf
  WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 3};

cqlsh> USE udf;

cqlsh:udf> CREATE OR REPLACE FUNCTION udf.timeuuid_as_us ( t timeuuid ) 
RETURNS NULL ON NULL INPUT
RETURNS bigint LANGUAGE Java AS '
  long msb = t.getMostSignificantBits();
  return
    ( ((msb >> 32) & 0x00000000FFFFFFFFL)
    | ((msb & 0x00000000FFFF0000L) << 16)
    | ((msb & 0x0000000000000FFFL) << 48)
    ) / 10
    - 12219292800000000L;
';

cqlsh:udf> SELECT
  toUnixTimestamp(now())    AS now_ms
, udf.timeuuid_as_us(now()) AS now_us
FROM system.local;

 now_ms        | now_us
---------------+------------------
 1525995892841 | 1525995892841000
0
druud62