在时间戳列上使用等号运算符的 Cassandra 查询不起作用
Cassandra query with equals operator on timestamp column not working
我在 Cassandra 中创建了一个 table 如下:
CREATE TABLE sp.status(
ams text,
load_start_time timestamp,
file_path text,
file_timestamp timestamp,
host text,
load_end_time timestamp,
records_ignored int,
records_imported int,
records_in_file int,
status text,
PRIMARY KEY (ams, load_start_time)
) WITH CLUSTERING ORDER BY (load_start_time DESC)
我想 select 从特定日期开始的一行。当我使用 > 运算符时,一切都按预期工作。但是,如果我使用 = 运算符,则不会返回任何数据。
SELECT * FROM sp.status WHERE ams = 'RRG' AND load_start_time='2016-01-20 10:10:27' allow filtering;
数据库中有一行包含 load_start_time 的值,如果在上面的查询中我将 = 替换为 > for load_start_time.
,则会返回该行
有人可以解释为什么会这样吗?
我实际上需要这个用于 DELETE 语句,但我不能使用范围运算符,只能使用 =.
我打赌这是不同时区造成的。尝试将您的区域包含在 ...AND load_start_time='2016-01-20 10:10:27.000+0200'
之类的语句中
您是使用 dateOf(now())
还是使用其他包含毫秒精度的方法插入行? TIMESTAMP 将存储毫秒,但 不会 显示它。检查这个例子:
CREATE TABLE Whosebug.timestamptest (
userid text,
activetime timestamp,
value text,
PRIMARY KEY (userid, activetime)
) WITH CLUSTERING ORDER BY (activetime ASC)
INSERT INTO timestamptest (userid,activetime,value) VALUES ('d',dateof(now()),'value1');
INSERT INTO timestamptest (userid,activetime,value) VALUES ('d','2016-01-22 14:57:54+0000','value2');
SELECT userid, value, activetime, blobAsBigint(timestampAsBlob(activetime))
FROM timestamptest WHERE userid='d';
userid | value | activetime | system.blobasbigint(system.timestampasblob(activetime))
--------+--------+--------------------------+---------------------------------------------------------
d | value2 | 2016-01-22 14:57:54+0000 | 1453474674000
d | value1 | 2016-01-22 14:57:54+0000 | 1453474674912
(2 rows)
通过在 blobAsBigint(timestampAsBlob())
嵌套函数中包装 activetime,我可以看到通过 dateOf(now())
(912) 输入的时间有毫秒数,但作为文本输入的时间没有。正如您所发现的,当需要完成 in-place 更新或删除时,这可能会出现问题。
尝试使用 blobAsBigint(timestampAsBlob())
查看是否存在毫秒数,然后将这些毫秒数添加到您的 DELETE 操作的时间戳值中。例如:
DELETE FROM timestamptest WHERE userid='d' AND activetime='2016-01-22 14:57:54.912+0000';
关于"unable to coerce '2016-04-06 13:06:11.534000' to a formatted date (long)"错误,虽然时间戳列在所有版本中实际上存储的是毫秒,但根据版本查询的方式似乎有些差异:
Cassandra <=2.1 好像不支持毫秒查询:yyyy-mm-dd'T'HH:mm:ssZ
https://docs.datastax.com/en/cql/3.1/cql/cql_reference/timestamp_type_r.html
而 >=3.0 支持它:yyyy-mm-dd'T'HH:mm:ss.ffffffZ
https://docs.datastax.com/en/cql/3.3/cql/cql_reference/timestamp_type_r.html
我验证了能够 select/insert 在较新的集群中,但不能在旧集群中使用我的 IDE 连接到 9160 Thrift 端口,尚未在 cqlsh 上尝试过:
INSERT INTO "sp.status"("ams", "load_start_time")
VALUES('RRG', '2018-05-01T16:57:18.123+0200')
;
-- same with select, works on new cluster but not old
SELECT * FROM sp.status WHERE ams = 'RRG' AND load_start_time='2018-05-01T16:57:18.123+0200'
;
虽然驱动程序似乎能够映射 java 日期并在新旧集群中存储毫秒数。
=Cassandra 2.1 cqlsh uses native binary protocol (9042), previous versions use thrift (9160) although this should not change.
我在 Cassandra 中创建了一个 table 如下:
CREATE TABLE sp.status(
ams text,
load_start_time timestamp,
file_path text,
file_timestamp timestamp,
host text,
load_end_time timestamp,
records_ignored int,
records_imported int,
records_in_file int,
status text,
PRIMARY KEY (ams, load_start_time)
) WITH CLUSTERING ORDER BY (load_start_time DESC)
我想 select 从特定日期开始的一行。当我使用 > 运算符时,一切都按预期工作。但是,如果我使用 = 运算符,则不会返回任何数据。
SELECT * FROM sp.status WHERE ams = 'RRG' AND load_start_time='2016-01-20 10:10:27' allow filtering;
数据库中有一行包含 load_start_time 的值,如果在上面的查询中我将 = 替换为 > for load_start_time.
,则会返回该行有人可以解释为什么会这样吗?
我实际上需要这个用于 DELETE 语句,但我不能使用范围运算符,只能使用 =.
我打赌这是不同时区造成的。尝试将您的区域包含在 ...AND load_start_time='2016-01-20 10:10:27.000+0200'
您是使用 dateOf(now())
还是使用其他包含毫秒精度的方法插入行? TIMESTAMP 将存储毫秒,但 不会 显示它。检查这个例子:
CREATE TABLE Whosebug.timestamptest (
userid text,
activetime timestamp,
value text,
PRIMARY KEY (userid, activetime)
) WITH CLUSTERING ORDER BY (activetime ASC)
INSERT INTO timestamptest (userid,activetime,value) VALUES ('d',dateof(now()),'value1');
INSERT INTO timestamptest (userid,activetime,value) VALUES ('d','2016-01-22 14:57:54+0000','value2');
SELECT userid, value, activetime, blobAsBigint(timestampAsBlob(activetime))
FROM timestamptest WHERE userid='d';
userid | value | activetime | system.blobasbigint(system.timestampasblob(activetime))
--------+--------+--------------------------+---------------------------------------------------------
d | value2 | 2016-01-22 14:57:54+0000 | 1453474674000
d | value1 | 2016-01-22 14:57:54+0000 | 1453474674912
(2 rows)
通过在 blobAsBigint(timestampAsBlob())
嵌套函数中包装 activetime,我可以看到通过 dateOf(now())
(912) 输入的时间有毫秒数,但作为文本输入的时间没有。正如您所发现的,当需要完成 in-place 更新或删除时,这可能会出现问题。
尝试使用 blobAsBigint(timestampAsBlob())
查看是否存在毫秒数,然后将这些毫秒数添加到您的 DELETE 操作的时间戳值中。例如:
DELETE FROM timestamptest WHERE userid='d' AND activetime='2016-01-22 14:57:54.912+0000';
关于"unable to coerce '2016-04-06 13:06:11.534000' to a formatted date (long)"错误,虽然时间戳列在所有版本中实际上存储的是毫秒,但根据版本查询的方式似乎有些差异:
Cassandra <=2.1 好像不支持毫秒查询:yyyy-mm-dd'T'HH:mm:ssZ https://docs.datastax.com/en/cql/3.1/cql/cql_reference/timestamp_type_r.html
而 >=3.0 支持它:yyyy-mm-dd'T'HH:mm:ss.ffffffZ https://docs.datastax.com/en/cql/3.3/cql/cql_reference/timestamp_type_r.html
我验证了能够 select/insert 在较新的集群中,但不能在旧集群中使用我的 IDE 连接到 9160 Thrift 端口,尚未在 cqlsh 上尝试过:
INSERT INTO "sp.status"("ams", "load_start_time")
VALUES('RRG', '2018-05-01T16:57:18.123+0200')
;
-- same with select, works on new cluster but not old
SELECT * FROM sp.status WHERE ams = 'RRG' AND load_start_time='2018-05-01T16:57:18.123+0200'
;
虽然驱动程序似乎能够映射 java 日期并在新旧集群中存储毫秒数。
=Cassandra 2.1 cqlsh uses native binary protocol (9042), previous versions use thrift (9160) although this should not change.