Cassandra cqlsh - как показать микросекунды/миллисекунды для столбцов меток времени?

Я вставляю в таблицу Cassandra столбцы с метками времени. Данные, которые у меня есть, поступают с точностью до микросекунды, поэтому строка данных времени выглядит так:

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

Однако в cqlsh, когда я запускаю запрос на выборку, микросекундные данные не отображаются, я могу видеть время только с точностью до секунды. Данные 234 микросекунд не отображаются.

Я думаю, у меня есть два вопроса:

1) Захватывает ли Cassandra микросекунды с типом данных timestamp? Я думаю, да?

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;

person WillZ    schedule 16.02.2015    source источник
comment
Можете ли вы отредактировать свой пост с определением таблицы, запросом INSERT и SELECT? Я не буду знать наверняка, пока не увижу эту информацию, но ваша проблема может быть связана с этим: stackoverflow.com/questions/26237940/   -  person Aaron    schedule 16.02.2015
comment
Только что обновил свой пост, как вы и просили. Дайте мне знать, если это недостаточно ясно. Спасибо.   -  person WillZ    schedule 16.02.2015


Ответы (5)


Пытаясь ответить на ваши вопросы, я немного покопался в этом.

  1. Захватывает ли Cassandra микросекунды с типом данных timestamp?

Микросекунды нет, миллисекунды да. Если я создам вашу таблицу, вставлю строку и попытаюсь запросить ее по усеченному времени, это не сработает:

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-5870), но он был решен как "Выигран не исправить."

  1. Как я могу увидеть это с помощью cqlsh для проверки?

Один из возможных способов убедиться, что миллисекунды действительно существуют, — это вложить функцию 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)
person Aaron    schedule 16.02.2015
comment
Спасибо за подробный ответ, это очень полезно. Я могу работать с решением, которое у вас есть. Я предполагаю, что на практике я бы программно вернул временную метку, так что пока это работает, все должно быть в порядке. Есть ли предпочтение хранить метку времени в формате bigint в этом случае? - person WillZ; 17.02.2015
comment
@Will Честно говоря, это зависит от вашего варианта использования. Если вас беспокоит точность времени, то лучше всего сохранить ее как timeuuid. Но если миллисекунды больше относятся к полю полезной нагрузки или упорядочению результатов, тогда я вижу, что bigint работает на вас. - person Aaron; 17.02.2015
comment
Да, для меня порядок имеет значение. будет думать об этом. Спасибо! - person WillZ; 17.02.2015
comment
@Без проблем, рад, что смог помочь! - person Aaron; 17.02.2015
comment
Есть ли способ получить временную метку с помощью функции типа timestampAsBlob в node-cassandra-cql? - person booleanhunter; 07.06.2015
comment
Это было исправлено в Cassandra 3.4: issues.apache.org/jira/browse/CASSANDRA-10428. - person eprothro; 13.04.2016

Вы можете настроить формат вывода объектов datetime в файле .cassandra/cqlshrc, используя Синтаксис 'strftime'.

К сожалению, директива %f для микросекунд (похоже, директивы для миллисекунд нет) не работает для более старых версий Python, что означает, что вам нужно вернуться к решению blobAsBigint(timestampAsBlob(date)).

person Tom    schedule 13.03.2015

Я думаю, что под «микросекундами» (например, 03.234567) вы подразумеваете «миллисекунды» (например, (03.234).

Проблема здесь заключалась в ошибке cqlsh, которая не поддерживала доли секунды при работе с метками времени.

Таким образом, хотя ваше значение в миллисекундах было сохранено на фактическом уровне сохраняемости (cassandra), оболочка (cqlsh) не смогла их отобразить.

Это было верно, даже если бы вы изменили time_format в .cqlshrc для отображения дробных секунд с директивой %f (например, %Y-%m-%d %H:%M:%S.%f%z). В этой конфигурации cqlsh будет отображать 3.000000 для нашего значения 3,234, поскольку проблема заключалась в том, как cqlsh загружал объекты даты и времени без загрузки неполных секунд.

При этом проблема была исправлена ​​в CASSANDRA-10428 и выпущена в Cassandra 3.4.

person eprothro    schedule 13.04.2016

Невозможно отобразить микросекунды (1 миллионную долю секунды) с использованием «отметки времени» типа данных Cassandra, потому что наибольшая точность, доступная для этого типа данных, составляет миллисекунды (1 тысячная секунды).

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

Значения типа timestamp кодируются как 64-битные целые числа со знаком, представляющие количество миллисекунд со стандартного базового времени, известного как эпоха.

person user892703    schedule 26.01.2016

Некоторый связанный код:

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
person druud62    schedule 11.05.2018