Tous les produits
Search
Centre de documentation

MaxCompute:Requêtes de voyage dans le temps et requêtes incrémentielles

Dernière mise à jour :Aug 10, 2026

Les tables Delta prennent en charge deux modes de requête historique : les requêtes de voyage dans le temps et les requêtes incrémentielles. Une requête de voyage dans le temps lit un instantané de la table à un moment ou une version spécifique. Une requête incrémentielle renvoie uniquement les lignes qui ont changé entre deux moments ou entre deux versions.

Ces deux types de requête étendent la syntaxe standard du langage de requête de données (DQL) MaxCompute. La syntaxe DQL complète et ses limites s'appliquent, avec une exception : la clause FROM accepte un qualificateur temporel ou de version.

Syntaxe

[WITH <cte>[, ...] ]
SELECT [ALL | DISTINCT] <select_expr>[, <except_expr>)][, <replace_expr>] ...
       FROM <table_reference>
       [TIMESTAMP | VERSION AS OF expr]
       [TIMESTAMP | VERSION BETWEEN start_expr AND end_expr]
       [WHERE <where_condition>]
       [GROUP BY {<col_list> | ROLLUP(<col_list>)}]
           [HAVING <having_condition>]
       [ORDER BY <order_condition>]
       [DISTRIBUTE BY <distribute_condition> [SORT BY <sort_condition>]|[ CLUSTER BY <cluster_condition>] ]
       [LIMIT <number>]
       [WINDOW <window_clause>]

Utilisez TIMESTAMP | VERSION AS OF expr pour les requêtes de voyage dans le temps et TIMESTAMP | VERSION BETWEEN start_expr AND end_expr pour les requêtes incrémentielles.

Requêtes de voyage dans le temps

Une requête de voyage dans le temps renvoie un instantané historique de la table, c'est-à-dire l'état des données au moment spécifié ou avant celui-ci.

TIMESTAMP AS OF

SELECT * FROM <table> TIMESTAMP AS OF <expr>

expr accepte l'un des formats suivants :

Format Exemple Description
Chaîne TIMESTAMP '2023-01-01 00:00:00.123' Horodatage précis avec millisecondes
Chaîne DATETIME '2023-01-01 00:00:00' Horodatage sans millisecondes
Chaîne DATE '2023-01-01' Date uniquement ; l'heure est définie par défaut à minuit
current_timestamp() current_timestamp() Heure actuelle
getDate() + N getDate() - 3600 N secondes par rapport à maintenant ; négatif = passé, positif = futur
get_latest_timestamp(tablename [, number]) get_latest_timestamp('mf_tt2', 2) Horodatage de la Nième opération DML la plus récente (par défaut : 1 = dernière). L'horodatage renvoyé peut être identique pour différentes valeurs de number.

Pour un accès inter-projets, formatez tablename sous la forme ProjectName.TableName. Pour le modèle à trois couches, utilisez ProjectName.SchemaName.TableName.

Limites :

  • La plage de requête valide est [CreateTableTimestamp, expr], où CreateTableTimestamp correspond à l'heure de validation de la création de la table.

  • Si expr est antérieur à l'heure de création de la table ou remonte à plus de N heures, une erreur est renvoyée. N est défini par la propriété acid.data.retain.hours lors de la création de la table. Par exemple, si acid.data.retain.hours est 72 et que expr remonte à 80 heures, la requête échoue.

  • Si expr remonte exactement à N heures, une erreur peut également être renvoyée en raison de la latence au niveau de la seconde dans les systèmes internes.

Avertissement

Évitez d'utiliser TIMESTAMP AS OF current_timestamp() - <seconds> pour les requêtes proches de la limite de rétention. Utilisez get_latest_timestamp() pour référencer en toute sécurité les validations récentes.

VERSION AS OF

SELECT * FROM <table> VERSION AS OF <expr>

expr accepte :

Format Exemple Description
Constante BIGINT 3 Un numéro de version spécifique
get_latest_version(tablename [, number]) get_latest_version('mf_tt2', 2) Version de la Nième opération DML la plus récente (par défaut : 1 = dernière). Contrairement à get_latest_timestamp, la version renvoyée varie avec chaque valeur de number.

Pour le formatage de tablename , suivez les mêmes règles que pour get_latest_timestamp().

Limites :

  • Chaque opération DML génère un numéro de version strictement croissant. Exécutez SHOW HISTORY FOR TABLE/PARTITION pour afficher toutes les versions.

  • La plage de versions valides est [CreateTableVersion, expr]. La valeur par défaut de CreateTableVersion est 1.

  • Si la version correspond à une heure de validation antérieure à N heures (où N = acid.data.retain.hours), ou si la version est inférieure à 1, une erreur est renvoyée.

  • Si expr dépasse la dernière version DML, une erreur est renvoyée.

Remarque

Utilisez get_latest_version() pour récupérer un numéro de version valide et éviter les erreurs de plage hors limites.

Requêtes incrémentielles

Une requête incrémentielle renvoie uniquement les lignes qui ont été ajoutées ou modifiées dans une plage de temps ou de versions, ce qui équivaut au delta entre deux instantanés.

Remarque

Les données générées par la compaction ne sont pas considérées comme de nouvelles données et sont exclues des résultats des requêtes incrémentielles.

TIMESTAMP BETWEEN

SELECT * FROM <table> TIMESTAMP BETWEEN <start_expr> AND <end_expr>

La plage temporelle est (start_expr, end_expr] — ouverte à gauche, fermée à droite. Les deux expressions suivent les mêmes formats pris en charge par TIMESTAMP AS OF.

Limites :

  • Si start_expr est antérieur à l'heure de création de la table ou remonte à plus de N heures, une erreur est renvoyée. N = acid.data.retain.hours.

  • Si end_expr est postérieur à la dernière heure de validation DML, le comportement dépend de acid.incremental.query.out.of.time.range.enabled :

    • Par défaut (false) : une erreur est renvoyée.

    • Défini sur true : la requête renvoie toutes les données incrémentielles dans la plage (start_expr, end_expr].

Remarque

Pour autoriser les requêtes qui s'étendent au-delà de la dernière validation, définissez la propriété sur true :

ALTER TABLE <table> SET tblproperties("acid.incremental.query.out.of.time.range.enabled"="true");

VERSION BETWEEN

SELECT * FROM <table> VERSION BETWEEN <start_expr> AND <end_expr>

La plage de versions est (start_expr, end_expr] — ouverte à gauche, fermée à droite. Les deux expressions suivent les mêmes formats pris en charge par VERSION AS OF.

Limites :

  • Le système résout start_expr en une heure de validation. Si cette heure remonte à plus de N heures ou si la version est inférieure à 1, une erreur est renvoyée. N = acid.data.retain.hours.

  • Si end_expr dépasse la dernière version DML, le comportement dépend de acid.incremental.query.out.of.time.range.enabled :

    • Par défaut (false) : une erreur est renvoyée.

    • Défini sur true : la requête renvoie toutes les données incrémentielles dans la plage (start_expr, end_expr].

Remarques d'utilisation

  • Seules les tables Delta prennent en charge les requêtes de voyage dans le temps et les requêtes incrémentielles.

  • Clés dupliquées : Lorsque plusieurs lignes partagent la même clé primaire, seule la dernière ligne est renvoyée. Les lignes à l'état DELETE sont exclues.

  • Capture des données modifiées (CDC) : L'interrogation de l'état de mise à jour des données dans des formats similaires à la capture des données modifiées (CDC) n'est pas encore prise en charge et est prévue pour une prochaine version.

  • Tables supprimées ou renommées : Vous ne pouvez pas interroger les données historiques d'une table après sa suppression ou son renommage. Restaurez d'abord la table, puis exécutez la requête.

  • Même table, plusieurs qualificateurs : Si vous souhaitez effectuer une requête de voyage dans le temps ou une requête incrémentielle sur la même table dans une instruction SQL, vous devez définir les horodatages ou les versions des requêtes sur les mêmes valeurs.

  • Tables partitionnées : Spécifiez une partition dans la clause WHERE pour limiter l'analyse à cette partition et réduire le temps de requête.

  • Concurrence : Les tables Delta utilisent le contrôle de concurrence multiversion (MVCC) pour isoler les lectures et écritures simultanées. Le niveau d'isolation Read Committed est pris en charge.

Exemples

Les exemples suivants utilisent une table Delta partitionnée mf_tt2.

Configuration des données d'exemple

-- Table creation. Version = 1.
-- Run "SHOW HISTORY FOR TABLE mf_tt2" to confirm.
CREATE TABLE mf_tt2 (
  pk bigint NOT NULL PRIMARY KEY,
  val bigint NOT NULL)
PARTITIONED BY (dd string, hh string)
tblproperties ("transactional"="true");

-- INSERT OVERWRITE. Version = 2.
INSERT OVERWRITE TABLE mf_tt2 PARTITION (dd='01', hh='01') VALUES (1, 1), (2, 2), (3, 3);

-- INSERT INTO. Version = 3.
INSERT INTO TABLE mf_tt2 PARTITION (dd='01', hh='01') VALUES (3, 30), (4, 4), (5, 5);

Pour vérifier l'heure de création de la table et l'historique des versions avant d'exécuter les requêtes :

-- Get the table creation timestamp
DESC EXTENDED mf_tt2;

Le résultat suivant est renvoyé.

+------------------------------------------------------------------------------------+
| Owner: ALIYUN$****_doctest@test.aliyunid.com | Project: doc_test_prod                               |
| TableComment:                                                                      |
+------------------------------------------------------------------------------------+
| CreateTime:               2023-06-26 09:31:38                                      |
| LastDDLTime:              2023-06-26 09:31:38                                      |
| LastModifiedTime:         2023-06-26 09:32:31                                      |
+------------------------------------------------------------------------------------+
| InternalTable: YES      | Size: 8541                                               |
+------------------------------------------------------------------------------------+
| Native Columns:                                                                    |
+------------------------------------------------------------------------------------+
| Field    | Type   | Label | ExtendedLabel | Nullable | DefaultValue | Comment      |
+------------------------------------------------------------------------------------+
| pk       | bigint |       |               | false    | NULL         |              |
| val      | bigint |       |               | false    | NULL         |              |
+------------------------------------------------------------------------------------+
| Partition Columns:                                                                 |
+------------------------------------------------------------------------------------+
| dd              | string     |                                                     |
| hh              | string     |                                                     |
+------------------------------------------------------------------------------------+
| Extended Info:                                                                     |
+------------------------------------------------------------------------------------+
| TableID:                  bec515a56cc9492c8f906a224c62****                         |
| IsArchived:               false                                                    |
| PhysicalSize:             25623                                                    |
| FileNum:                  9                                                        |
| StoredAs:                 AliOrc                                                   |
| CompressionStrategy:      normal                                                   |
| ClusterType:              hash                                                     |
| BucketNum:                16                                                       |
| ClusterColumns:           [pk]                                                     |
| SortColumns:              [pk ASC]                                                 |
+------------------------------------------------------------------------------------+
-- Get all DML version numbers and commit times
SHOW HISTORY FOR TABLE mf_tt2 PARTITION (dd='01', hh='01');

Le résultat suivant est renvoyé.

ID = 20230626021756157ghict5k****
ObjectType      ObjectId                                ObjectName              VERSION(LSN)            Time                    Operation
PARTITION       4764c8e1cb634a4fb9c21f3fc850****        dd=01/hh=01             0000000000000002        2023-06-26 09:31:56     CREATE
PARTITION       4764c8e1cb634a4fb9c21f3fc850****        dd=01/hh=01             0000000000000003        2023-06-26 09:32:32     APPEND

La sortie de SHOW HISTORY affiche chaque opération, son numéro de version, son heure de validation et son type d'opération (CREATE, APPEND, etc.).

Exemples de requêtes de voyage dans le temps

Instantané à une date et heure spécifiques — toutes les données à partir de 09:33:00 :

SELECT * FROM mf_tt2 TIMESTAMP AS OF '2023-06-26 09:33:00' WHERE dd = '01' AND hh = '01';

Renvoie les 5 lignes écrites par les versions 2 et 3 (pk 1–5, avec pk=3 affichant val=30 depuis la dernière écriture).

Instantané à la version 2 — avant l'instruction INSERT INTO :

SELECT * FROM mf_tt2 VERSION AS OF 2 WHERE dd = '01' AND hh = '01';

Renvoie les 3 lignes de l'instruction INSERT OVERWRITE : pk=1, pk=2, pk=3 (val=3).

Instantané à l'heure actuelle :

SELECT * FROM mf_tt2 TIMESTAMP AS OF current_timestamp() WHERE dd = '01' AND hh = '01';

Instantané il y a 10 secondes :

SELECT * FROM mf_tt2 TIMESTAMP AS OF current_timestamp() - 10 WHERE dd = '01' AND hh = '01';

Instantané à la deuxième validation la plus récente (utilisation de get_latest_timestamp) :

SELECT * FROM mf_tt2 TIMESTAMP AS OF get_latest_timestamp('mf_tt2', 2) WHERE dd = '01' AND hh = '01';

Renvoie les 3 lignes de la version 2.

Instantané à la deuxième version la plus récente (utilisation de get_latest_version) :

SELECT * FROM mf_tt2 VERSION AS OF get_latest_version('mf_tt2', 2) WHERE dd = '01' AND hh = '01';

Renvoie les 3 lignes de la version 2.

Exemples de requêtes incrémentielles

Modifications entre deux horodatages de validation :

SELECT * FROM mf_tt2 TIMESTAMP BETWEEN '2023-06-26 09:31:40' AND '2023-06-26 09:32:00' WHERE dd = '01' AND hh = '01';

Renvoie les 3 lignes écrites par la version 2.

Modifications entre la version 2 et la version 3 :

SELECT * FROM mf_tt2 VERSION BETWEEN 2 AND 3 WHERE dd = '01' AND hh = '01';

Renvoie les 3 lignes écrites par la version 3 : pk=3 (val=30), pk=4, pk=5.

Dernières 300 secondes avec acid.incremental.query.out.of.time.range.enabled défini sur false (par défaut) :

SELECT * FROM mf_tt2 TIMESTAMP BETWEEN current_timestamp() - 301 AND current_timestamp() WHERE dd = '01' AND hh='01';

Renvoie une erreur car end_expr dépasse l'horodatage de la dernière validation :

FAILED: ODPS-0130071:[0,0] Semantic analysis exception - physical plan generation failed:
com.aliyun.odps.meta.exception.MetaException: ...
Incremental query can't exceed current version. Current version timestamp: 2023-06-26 09:32:32, input timestamp is: 2023-06-26 10:47:55

Pour permettre à la requête de s'étendre au-delà de la dernière validation, activez la propriété :

ALTER TABLE mf_tt2 SET tblproperties("acid.incremental.query.out.of.time.range.enabled"="true");

Réexécutez ensuite la requête. Le résultat est vide (aucune nouvelle donnée n'a été écrite au cours des 300 dernières secondes) :

+------------+------------+----+----+
| pk         | val        | dd | hh |
+------------+------------+----+----+
+------------+------------+----+----+

Modifications de la troisième validation la plus récente à la plus récente :

SELECT * FROM mf_tt2 TIMESTAMP BETWEEN get_latest_timestamp('mf_tt2', 3) AND get_latest_timestamp('mf_tt2') WHERE dd = '01' AND hh = '01';

Renvoie les 5 lignes (couvre les validations des versions 2 et 3).

Modifications de la troisième version la plus récente à la plus récente :

SELECT * FROM mf_tt2 VERSION BETWEEN get_latest_version('mf_tt2', 3) AND get_latest_version('mf_tt2') WHERE dd = '01' AND hh = '01';

Renvoie les 5 lignes.