web-dev-qa-db-fra.com

Cassandra cqlsh - Comment afficher des microsecondes/millisecondes pour des colonnes d’horodatage?

J'insère dans une table Cassandra avec des colonnes d'horodatage. Les données que j'ai ont une précision de l'ordre de la microseconde. La chaîne de données de temps ressemble à ceci:

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

Cependant, dans cqlsh, lorsque je lance une requête select, les données en microsecondes ne sont pas affichées, je ne peux que voir le temps passer en seconde précision. Les données 234 microsecondes ne sont pas affichées.

Je suppose que j'ai deux questions:

1) Cassandra enregistre-t-il des microsecondes avec le type de données timestamp? Je suppose que oui?

2) Comment puis-je voir cela avec cqlsh pour vérifier? 

Définition du tableau:

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

Insérer une requête exécutée avec Java PreparedStatment:

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

La requête sélectionnée était simplement:

select * from data;
20
WillZ

Afin de répondre à vos questions, j'ai un peu creusé le sujet.

  1. Cassandra enregistre-t-il des microsecondes avec le type de données timestamp?

Microsecondes non, millisecondes oui. Si je crée votre table, insère une ligne et essaie de l'interroger avant l'heure tronquée, cela ne fonctionne pas:

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)

Mais lorsque je demande les mêmes valeurs id et type en spécifiant des millisecondes:

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)

Les millisecondes sont donc bien là. Un ticket JIRA a été créé pour ce problème ( CASSANDRA-5870 ), mais le problème a été résolu avec le message "Ne résout pas le problème".

  1. Comment puis-je voir cela avec cqlsh pour vérifier?

Une façon possible de vérifier que les millisecondes sont bien présentes consiste à imbriquer la fonction timestampAsBlob() à l'intérieur de blobAsBigint(), comme ceci:

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)

Bien que cela ne soit pas optimal, vous pouvez clairement voir la valeur de la milliseconde de "234" à la fin. Cela devient encore plus évident si j'ajoute une ligne pour le même horodatage, mais sans millisecondes:

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)
44
Aaron

Vous pouvez configurer le format de sortie des objets datetime dans le fichier .cassandra/cqlshrc, en utilisant la syntaxe python 'strftime'.

Malheureusement, la directive %f pour les microsecondes (il ne semble pas y avoir de directive pour les millisecondes) ne fonctionne pas pour les anciennes versions de Python, ce qui signifie que vous devez revenir à la solution blobAsBigint(timestampAsBlob(date)).

7
Tom

Je pense que par "microsecondes" (par exemple 03.234567), vous voulez dire "millisecondes" (par exemple (03.234).

Le problème ici était un bogue cqlsh qui ne supportait pas les fractions de seconde lors du traitement des horodatages.

Ainsi, alors que votre valeur en millisecondes a été préservée dans la couche de persistance réelle (cassandra), le shell (cqlsh) n'a pas réussi à les afficher. 

Cela était vrai même si vous deviez modifier time_format dans .cqlshrc pour afficher des fractions de seconde avec une directive %f (par exemple, %Y-%m-%d %H:%M:%S.%f%z). Dans cette configuration, cqlsh rendrait 3.000000 pour notre valeur 3.234, car le problème était de savoir comment cqlsh chargeait les objets datetime sans charger les secondes partielles.

Cela étant dit, ce problème a été résolu dans CASSANDRA-10428 , et publié dans Cassandra 3.4 .

2
eprothro

Il est impossible d'afficher des microsecondes (1 millionième de seconde) à l'aide du type de données Cassandra 'timestamp' car la plus grande précision disponible pour ce type de données est la milliseconde (1 millième de seconde).

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

Les valeurs du type d'horodatage sont codées sous forme d'entiers signés de 64 bits représentant un nombre de millisecondes depuis le temps de base standard connu sous le nom de l'époque

1
user892703

Quelques codes liés:

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