タイムスタンプ列を含む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;
あなたの質問に答えるために、私はこれについて少し掘り下げました。
マイクロ秒いいえ、ミリ秒はい。テーブルを作成し、行を挿入し、切り捨てられた時間までにクエリを実行しようとすると、機能しません。
_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)
_
しかし、ミリ秒を指定して同じid
とtype
の値を照会すると:
_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つの可能な方法は、次のように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)
_
「マイクロ秒」(例: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 でリリースされました。
Cassandraデータ型 'timestamp'を使用してマイクロ秒(100万分の1秒)を表示することは不可能です。そのデータ型で使用できる最大精度はミリ秒(1000分の1秒)であるためです。
http://docs.datastax.com/en/cql/3.1/cql/cql_reference/timestamp_type_r.html
タイムスタンプタイプの値は、エポックとして知られる標準のベースタイムからのミリ秒数を表す64ビット符号付き整数としてエンコードされます。
いくつかの関連コード:
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