insert timestamp cassandra
Cassandra cqlsh: ¿cómo mostrar microsegundos/milisegundos para las columnas de marca de tiempo? (5)
Estoy insertando en una tabla de Cassandra con columnas de marca de tiempo. Los datos que tengo vienen con una precisión de microsegundos, por lo que la cadena de datos de tiempo se ve así:
2015-02-16T18: 00: 03.234 + 00: 00
Sin embargo, en cqlsh, cuando ejecuto una consulta de selección, no se muestran los datos de microsegundos, solo puedo ver el tiempo hasta la segunda precisión. Los 234 microsegundos de datos no se muestran.
Supongo que tengo dos preguntas:
1) ¿Cassandra captura microsegundos con el tipo de datos de marca de tiempo? Mi conjetura es si?
2) ¿Cómo puedo ver eso con cqlsh para verificar?
Definición de la tabla:
create table data (
datetime timestamp,
id text,
type text,
data text,
primary key (id, type, datetime)
)
with compaction = {''class'' : ''DateTieredCompactionStrategy''};
Insertar consulta ejecutada con Java PreparedStatment:
insert into data (datetime, id, type, data) values(?, ?, ?, ?);
Seleccionar consulta fue simplemente:
select * from data;
Algún código relacionado:
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
Creo que por "microsegundos" (por ejemplo, 03.234567) te refieres a "milisegundos" (por ejemplo, (03.234).
El problema aquí fue un error cqlsh
que no cqlsh
segundos fraccionados al tratar con marcas de tiempo.
Entonces, mientras que su valor de milisegundos se conservó en la capa de persistencia real (cassandra), el shell (cqlsh) no pudo mostrarlos.
Esto fue cierto incluso si cambiara el time_format
de time_format
en .cqlshrc
para mostrar los segundos fraccionarios con una directiva %f
(por ejemplo, %Y-%m-%d %H:%M:%S.%f%z
). En esta configuración, cqlsh representaría 3.000000
para nuestro valor de 3.234, ya que el problema estaba en cómo cqlsh cargó los objetos de fecha y hora sin cargar los segundos parciales.
Dicho todo esto, este problema se solucionó en CASSANDRA-10428 y se publicó en Cassandra 3.4 .
En un esfuerzo por responder a sus preguntas, hice un poco de investigación en este caso.
- ¿Cassandra captura microsegundos con el tipo de datos de marca de tiempo?
Microsegundos no, milisegundos si. Si creo su tabla, inserto una fila e intento consultarla por el tiempo truncado, no funciona:
aploetz@cqlsh:> 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:> 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)
Pero cuando pregunto por los mismos valores de id
y type
mientras especifico milisegundos:
aploetz@cqlsh:> 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)
Así que los milisegundos están definitivamente ahí. Hubo un ticket JIRA creado para este problema ( CASSANDRA-5870 ), pero se resolvió como "No se solucionará".
- ¿Cómo puedo ver eso con cqlsh para verificar?
Una forma posible de verificar realmente que los milisegundos están efectivamente allí, es anidar la función timestampAsBlob()
dentro de blobAsBigint()
, de esta manera:
aploetz@cqlsh:> 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)
Si bien no es óptimo, aquí puede ver claramente el valor de milisegundos de "234" al final. Esto se vuelve aún más evidente si agrego una fila para la misma marca de tiempo, pero sin milisegundos:
aploetz@cqlsh:> 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:> 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)
Es imposible mostrar microsegundos (1 millonésima de segundo) con el tipo de datos de Cassandra ''timestamp'' porque la mayor precisión disponible para ese tipo de datos es milisegundos (1 milésima de segundo).
http://docs.datastax.com/en/cql/3.1/cql/cql_reference/timestamp_type_r.html
Los valores para el tipo de marca de tiempo se codifican como enteros con signo de 64 bits que representan una cantidad de milisegundos desde el tiempo base estándar conocido como la época
Puede configurar el formato de salida de los objetos de fecha y hora en el archivo .cassandra/cqlshrc
, utilizando la sintaxis ''strftime'' de python.
Desafortunadamente, la directiva %f
para microsegundos (no parece haber una directiva durante milisegundos) CASSANDRA-5870 para versiones antiguas de python, lo que significa que tiene que recurrir a la blobAsBigint(timestampAsBlob(date))
.