Comprendre et utiliser la fonction « Time Travel »

La fonction « Time Travel » de Snowflake permet d’accéder aux données historiques (c.-à-d. les données qui ont été modifiées ou supprimées) à tout moment au cours d’une période définie. C’est un outil puissant pour effectuer les tâches suivantes :

  • Restaurer des objets liés aux données (tables, schémas et bases de données) qui peuvent avoir été supprimés accidentellement ou intentionnellement.

  • Dupliquer et sauvegarder des données à partir des points clés dans le passé.

  • Analyser l’utilisation et la manipulation des données sur des périodes de temps précises.

Dans ce chapitre :

Introduction à la fonction « Time Travel »

Time Travel in Continuous Data Protection lifecycle

En utilisant Time Travel, vous pouvez effectuer les actions suivantes dans une période de temps définie :

  • Interroger les données du passé qui ont été mises à jour ou supprimées depuis.

  • Créer des clones de tables, de schémas et de bases de données entières à des points spécifiques dans le passé, ou avant.

  • Restaurer les tables, les schémas et les bases de données qui ont été détruites.

Une fois la période définie écoulée, les données sont déplacées dans Snowflake Fail-safe et ces actions ne peuvent plus être effectuées.

Extensions SQL Time Travel

Les extensions SQL suivantes ont été implémentées pour prendre en charge Time Travel :

  • Clause AT | BEFORE qui peut être spécifiée dans les instructions SELECT et les commandes CREATE … CLONE (immédiatement après le nom de l’objet). La clause utilise l’un des paramètres suivants pour identifier les données historiques exactes auxquelles vous souhaitez accéder :

    • TIMESTAMP

    • OFFSET (différence de temps en secondes par rapport au temps actuel)

    • STATEMENT (identificateur de l’instruction, par exemple requête ID)

  • commande UNDROP pour les tables, les schémas et les bases de données.

    Time Travel SQL extensions

Période de conservation des données

La période de conservation des données est un élément clé de la fonction « Time Travel » de Snowflake.

Lorsque des données d’une table sont modifiées, ce qui comprend aussi la suppression des données ou la destruction d’un objet contenant les données, Snowflake conserve l’état des données avant d’effectuer la mise à jour. La période de conservation des données spécifie le nombre de jours pendant lesquels ces données historiques sont conservées et, par conséquent, pendant lesquels les opérations de Time Travel (SELECT, CREATE… CLONE, UNDROP) peuvent être effectuées sur les données.

La période de conservation standard est de 1 jour (24 heures) et est automatiquement activée pour tous les comptes Snowflake :

  • Pour Snowflake Standard Edition, la période de conservation peut être définie sur 0 (ou revenir à la valeur par défaut de 1 jour) au niveau du compte et de l’objet (c.-à-d. des bases de données, schémas et tables).

  • Pour Snowflake Enterprise Edition (et versions supérieures) :

    • Pour les bases de données, les schémas et les tables transitoires, la période de conservation peut être définie sur 0 (ou revenir à la valeur par défaut de 1 jour). Il en va de même pour les tables temporaires.

    • Pour les bases de données, les schémas et les tables permanents, la période de conservation peut être définie sur une valeur comprise entre 0 et 90 jours.

Note

Une période de conservation de 0 jour pour un objet désactive la fonction Time Travel pour cet objet.

Lorsque la période de conservation d’un objet prend fin, les données historiques sont déplacées dans Snowflake Fail-safe :

  • Les données historiques ne sont plus disponibles pour l’interrogation.

  • Les objets passés ne peuvent plus être clonés.

  • Les objets passés qui ont été détruits ne peuvent plus être restaurés.

Pour spécifier la période de conservation des données pour Time Travel :

  • Le paramètre d’objet DATA_RETENTION_TIME_IN_DAYS peut être utilisé par vos utilisateurs ayant le rôle ACCOUNTADMIN pour définir la période de conservation par défaut de votre compte.

  • Le même paramètre peut être utilisé pour remplacer explicitement la valeur par défaut lors de la création de bases de données, de schémas et de tables individuelles.

  • La période de conservation des données pour une base de données, un schéma ou une table peut être modifiée à tout moment.

Activation et désactivation de Time Travel

Aucune tâche n’est requise pour activer Time Travel. Cette fonction est automatiquement activée avec la période de conservation standard de 1 jour.

Toutefois, vous pouvez passer à Snowflake Enterprise Edition pour permettre la configuration de périodes de conservation plus longues (jusqu’à 90 jours) pour les bases de données, les schémas et les tables. Notez que la conservation prolongée des données nécessite un stockage supplémentaire qui se reflétera dans vos frais de stockage mensuels. Pour plus d’informations sur les frais de stockage, voir Coûts de stockage pour Time Travel et Fail-safe.

La fonction Time Travel ne peut pas être désactivée pour un compte. Cependant, elle peut être désactivée pour des bases de données, schémas et tables individuels en indiquant DATA_RETENTION_TIME_IN_DAYS avec une valeur de 0 pour l’objet.

De plus, les utilisateurs dotés du rôle ACCOUNTADMIN peuvent définir DATA_RETENTION_TIME_IN_DAYS sur 0 au niveau du compte, ce qui signifie que toutes les bases de données (et par la suite tous les schémas et toutes les tables) créées dans le compte n’ont aucune durée de conservation par défaut. Toutefois, cette valeur par défaut peut être remplacée à tout moment pour tous schémas, bases de données, ou tables.

Attention

Avant de définir DATA_RETENTION_TIME_IN_DAYS sur 0 pour un objet, déterminez si vous souhaitez désactiver Time Travel pour l’objet, en particulier en ce qui concerne la récupération de l’objet s’il est détruit. La possibilité de restaurer des objets détruits sans période de conservation persiste uniquement pendant la durée de la session au cours de laquelle l’objet a été détruit. En d’autres termes, une fois qu’un objet sans période de conservation est détruit, vous ne pourrez pas le restaurer une fois la session terminée.

En règle générale, nous vous recommandons de conserver une valeur d’au moins 1 jour pour tout objet donné.

Spécification de la période de conservation des données pour un objet

Par défaut, la période de conservation maximale est de 1 jour (c.-à-d. 24 h). Avec Snowflake Enterprise Edition (et version supérieure), la valeur par défaut de votre compte peut être définie sur une valeur allant jusqu’à 90 jours :

  • Lors de la création d’une table, d’un schéma ou d’une base de données, le paramètre par défaut du compte peut être remplacé par le paramètre DATA_RETENTION_TIME_IN_DAYS dans la commande.

  • Si une période de conservation est spécifiée pour une base de données ou un schéma, elle est héritée par défaut pour tous les objets créés dans la base de données/le schéma.

Modification de la période de conservation des données pour un objet

Si vous modifiez la période de conservation des données pour une table, la nouvelle période de conservation affecte toutes les données actives ou celles actuellement conservées dans Time Travel. L’impact dépend si vous augmentez ou diminuez la période :

Augmentation de la conservation

Les données se trouvant actuellement dans Time Travel sont alors conservées pendant une période plus longue.

Par exemple, si vous avez une table avec une période de rétention de 10 jours et que vous augmentez cette période à 20 jours, les données qui auraient été supprimées après 10 jours sont maintenant conservées pendant 10 jours supplémentaires avant de passer dans Fail-safe.

Notez que cela ne s’applique pas aux données datant de plus de 10 jours et ayant déjà été transférées dans Fail-safe.

Diminution de la rétention

Réduit la durée de conservation des données dans Time Travel :

  • Pour les données actives modifiées après la réduction de la période de conservation, la nouvelle période plus courte s’applique.

  • Pour les données actuellement dans Time Travel :

    • Si les données sont toujours dans la nouvelle période plus courte, elles restent dans Time Travel.

    • Si les données sont en dehors de la nouvelle période, elles se déplacent dans Fail-safe.

Par exemple, si vous avez une table avec une période de conservation de 10 jours et que vous la réduisez à 1 jour, les données des jours 2 à 10 seront déplacées dans Fail-safe, ne laissant que 1 jour de données accessibles pour Time Travel.

Cependant, le processus de déplacement des données de Time Travel vers Fail-safe est effectué par un processus en arrière-plan. Par conséquent, la modification n’est pas immédiatement visible. Snowflake garantit que les données seront déplacées, mais ne précise pas quand le processus se terminera ; jusqu’à la fin du processus d’arrière-plan, les données sont toujours accessibles via Time Travel.

Pour modifier la période de conservation d’un objet, utilisez la commande ALTER <objet> correspondante. Par exemple, pour modifier la période de conservation d’une table :

CREATE TABLE mytable(col1 NUMBER, col2 DATE) DATA_RETENTION_TIME_IN_DAYS=90;

ALTER TABLE mytable SET DATA_RETENTION_TIME_IN_DAYS=30;

Attention

La modification de la période de conservation pour votre compte ou vos objets individuels modifie la valeur de tous les objets de niveau inférieur pour lesquels aucune période de conservation n’a été explicitement définie. Par exemple :

  • Si vous modifiez la période de conservation au niveau du compte, l’ensemble des bases de données, schémas et tables qui n’ont pas de période de conservation explicite héritent automatiquement de la nouvelle période de conservation.

  • Si vous modifiez la période de conservation au niveau du schéma, toutes les tables du schéma qui n’ont pas de période de conservation explicite héritent de la nouvelle période de conservation.

Gardez cela à l’esprit lorsque vous modifiez la période de conservation de votre compte ou de tout objet de votre compte, car le changement pourrait avoir des conséquences sur Time Travel que vous n’aviez pas anticipées ou prévues. En particulier, nous ne recommandons pas de modifier la période de conservation au niveau du compte à 0.

Interrogation des données historiques

Lorsqu’une opération DML est effectuée sur une table, Snowflake conserve les versions précédentes des données de la table pendant une période de temps définie. Ceci permet d’interroger les versions antérieures des données à l’aide de la clause AT | BEFORE.

Cette clause prend en charge l’interrogation des données exactement à un moment précis ou immédiatement avant un moment précis de l’historique de la table au cours de la période de conservation. Le point spécifié peut être basé sur l’heure (par exemple, un horodatage ou un décalage horaire par rapport au présent) ou il peut être l’ID d’une instruction complète (par exemple SELECT ou INSERT).

Par exemple :

  • La requête suivante sélectionne les données historiques d’une table à la date et à l’heure représentées par l’horodatage spécifié :

    SELECT * FROM my_table AT(TIMESTAMP => 'Mon, 01 May 2015 16:20:00 -0700'::timestamp);
    
  • La requête suivante sélectionne les données historiques d’une table d’il y a 5 minutes :

    SELECT * FROM my_table AT(OFFSET => -60*5);
    
  • La requête suivante sélectionne les données historiques à partir d’une table jusqu’à, mais sans inclure les modifications apportées par l’instruction spécifiée :

    SELECT * FROM my_table BEFORE(STATEMENT => '8e5d0ca9-005e-44e6-b858-a8f5b37c5726');
    

Note

Si la requête TIMESTAMP, OFFSET ou STATEMENT spécifiée dans la clause AT | BEFORE est située hors du délai de conservation des données de la table, la requête échoue et renvoie une erreur.

Clonage d’objets historiques

Outre les requêtes, la clause AT | BEFORE peut être utilisée avec le mot-clé CLONE dans la commande CREATE pour une table, un schéma ou une base de données afin de créer une duplication logique de l’objet à un point spécifique de l’historique de l’objet.

Par exemple :

  • La commande CREATE TABLE suivante crée un clone d’une table à la date et à l’heure représentées par l’horodatage spécifié :

    CREATE TABLE restored_table CLONE my_table
      AT(TIMESTAMP => 'Mon, 09 May 2015 01:01:00 +0300'::timestamp);
    
  • La commande CREATE SCHEMA suivante crée un clone d’un schéma et de tous ses objets tels qu’ils existaient 1 heure avant l’heure actuelle :

    CREATE SCHEMA restored_schema CLONE my_schema AT(OFFSET => -3600);
    
  • La commande CREATE DATABASE suivante crée un clone d’une base de données et de tous ses objets tels qu’ils existaient avant l’achèvement de l’instruction spécifiée :

    CREATE DATABASE restored_db CLONE my_db
      BEFORE(STATEMENT => '8e5d0ca9-005e-44e6-b858-a8f5b37c5726');
    

Destruction et restauration d’objets

Destruction d’objets

Lorsqu’une table, un schéma ou une base de données est détruit(e), il n’est pas immédiatement écrasé ou supprimé du système. À la place, il est conservé pour la période de conservation des données de l’objet pendant laquelle l’objet peut être restauré. Une fois les objets détruits déplacés vers Fail-safe, vous ne pouvez pas les restaurer.

Pour détruire une table, un schéma ou une base de données, utilisez les commandes suivantes :

Note

Après avoir détruit un objet, la création d’un objet portant le même nom ne restaure pas l’objet. À la place, cela crée une nouvelle version de l’objet. La version originale détruite est toujours disponible et peut être restaurée.

Restaurer un objet détruit restaure l’objet en place (c’est-à-dire que cela ne crée pas de nouvel objet).

Référencement des objets détruits

Les tables, schémas et bases de données détruits peuvent être répertoriés en utilisant les commandes suivantes avec le mot-clé HISTORY spécifié :

Par exemple :

SHOW TABLES HISTORY LIKE 'load%' IN mytestdb.myschema;

SHOW SCHEMAS HISTORY IN mytestdb;

SHOW DATABASES HISTORY;

La sortie inclut tous les objets détruits et une colonne DROPPED_ON supplémentaire qui affiche la date et l’heure auxquelles l’objet a été détruit. Si un objet a été détruit plus d’une fois, chaque version de l’objet est incluse comme une ligne séparée dans la sortie.

Note

Une fois que la période de conservation d’un objet est terminée et que l’objet a été purgé, il n’est plus affiché dans la sortie SHOW <type_objet> HISTORY.

Restauration d’objets

Un objet détruit qui n’a pas été purgé du système (c’est-à-dire que l’objet est affiché dans la sortie SHOW <type_objet> HISTORY) peut être restauré en utilisant les commandes suivantes :

Appeler UNDROP restaure l’objet à son état le plus récent avant que la commande DROP ne soit émise.

Par exemple :

UNDROP TABLE mytable;

UNDROP SCHEMA myschema;

UNDROP DATABASE mydatabase;

Note

Si un objet portant le même nom existe déjà, UNDROP échoue. Vous devez renommer l’objet existant, ce qui vous permet ensuite de restaurer la version précédente de l’objet.

Exigences en matière de contrôle d’accès et résolution de nom

Tout comme pour détruire un objet, un utilisateur doit posséder des privilèges OWNERSHIP sur un objet pour le restaurer. De plus, l’utilisateur doit avoir des privilèges CREATE sur le type d’objet pour la base de données ou le schéma où l’objet détruit sera restauré.

La restauration des tables et des schémas n’est prise en charge que dans le schéma actuel ou la base de données actuelle, même si un nom complet d’objet est spécifié.

Exemple : Destruction et restauration multiples de tables

Dans l’exemple suivant, le schéma mytestdb.public contient deux tables : loaddata1 et proddata1. La table loaddata1 est détruite et recréée deux fois, créant trois versions de la table :

  • Version actuelle

  • La seconde version détruite (c’est-à-dire la plus récente)

  • La première version détruite

L’exemple illustre ensuite comment restaurer les deux versions détruites de la table :

  1. Tout d’abord, la table actuelle portant le même nom est renommée en loaddata3. Ceci permet de restaurer la version la plus récente de la table détruite en fonction de l’horodatage.

  2. Ensuite, la version détruite la plus récente de la table est restaurée.

  3. La table restaurée est renommée loaddata2 pour permettre la restauration de la première version de la table détruite.

  4. Enfin, la première version de la table détruite est restaurée.

SHOW TABLES HISTORY;

+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+
| created_on                      | name      | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner  | retention_time | dropped_on                      |
|---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------|
| Tue, 17 Mar 2016 17:41:55 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 48   | 16248 | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:51:30 -0700 | PRODDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 12   | 4096  | PUBLIC | 1              | [NULL]                          |
+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+

DROP TABLE loaddata1;

SHOW TABLES HISTORY;

+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+
| created_on                      | name      | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner  | retention_time | dropped_on                      |
|---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------|
| Tue, 17 Mar 2016 17:51:30 -0700 | PRODDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 12   | 4096  | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:41:55 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 48   | 16248 | PUBLIC | 1              | Fri, 13 May 2016 19:04:46 -0700 |
+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+

CREATE TABLE loaddata1 (c1 number);
INSERT INTO loaddata1 VALUES (1111), (2222), (3333), (4444);

DROP TABLE loaddata1;

CREATE TABLE loaddata1 (c1 varchar);

SHOW TABLES HISTORY;

+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+
| created_on                      | name      | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner  | retention_time | dropped_on                      |
|---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------|
| Fri, 13 May 2016 19:06:01 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 0    | 0     | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:51:30 -0700 | PRODDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 12   | 4096  | PUBLIC | 1              | [NULL]                          |
| Fri, 13 May 2016 19:05:32 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 4    | 4096  | PUBLIC | 1              | Fri, 13 May 2016 19:05:51 -0700 |
| Tue, 17 Mar 2016 17:41:55 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 48   | 16248 | PUBLIC | 1              | Fri, 13 May 2016 19:04:46 -0700 |
+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+

ALTER TABLE loaddata1 RENAME TO loaddata3;

UNDROP TABLE loaddata1;

SHOW TABLES HISTORY;

+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+
| created_on                      | name      | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner  | retention_time | dropped_on                      |
|---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------|
| Fri, 13 May 2016 19:05:32 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 4    | 4096  | PUBLIC | 1              | [NULL]                          |
| Fri, 13 May 2016 19:06:01 -0700 | LOADDATA3 | MYTESTDB      | PUBLIC      | TABLE |         |            | 0    | 0     | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:51:30 -0700 | PRODDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 12   | 4096  | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:41:55 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 48   | 16248 | PUBLIC | 1              | Fri, 13 May 2016 19:04:46 -0700 |
+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+

ALTER TABLE loaddata1 RENAME TO loaddata2;

UNDROP TABLE loaddata1;

+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+
| created_on                      | name      | database_name | schema_name | kind  | comment | cluster_by | rows | bytes | owner  | retention_time | dropped_on                      |
|---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------|
| Tue, 17 Mar 2016 17:41:55 -0700 | LOADDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 48   | 16248 | PUBLIC | 1              | [NULL]                          |
| Fri, 13 May 2016 19:05:32 -0700 | LOADDATA2 | MYTESTDB      | PUBLIC      | TABLE |         |            | 4    | 4096  | PUBLIC | 1              | [NULL]                          |
| Fri, 13 May 2016 19:06:01 -0700 | LOADDATA3 | MYTESTDB      | PUBLIC      | TABLE |         |            | 0    | 0     | PUBLIC | 1              | [NULL]                          |
| Tue, 17 Mar 2016 17:51:30 -0700 | PRODDATA1 | MYTESTDB      | PUBLIC      | TABLE |         |            | 12   | 4096  | PUBLIC | 1              | [NULL]                          |
+---------------------------------+-----------+---------------+-------------+-------+---------+------------+------+-------+--------+----------------+---------------------------------+