{"id":14735,"date":"2023-02-23T10:04:31","date_gmt":"2023-02-23T10:04:31","guid":{"rendered":"https:\/\/bluetab.net\/?p=14735"},"modified":"2023-02-23T10:04:31","modified_gmt":"2023-02-23T10:04:31","slug":"snowflake-el-time-travel-sin-delorean-para-unos-datos-fail-safe","status":"publish","type":"post","link":"https:\/\/bluetab.es\/en\/2023\/02\/snowflake-el-time-travel-sin-delorean-para-unos-datos-fail-safe\/","title":{"rendered":"Snowflake, el Time Travel sin DeLorean para unos datos Fail-Safe."},"content":{"rendered":"<h1>Snowflake, el Time Travel sin DeLorean para unos datos Fail-Safe.<\/h1>\n<figure><a href=\"https:\/\/www.linkedin.com\/in\/roberto-garc%C3%ADa-parra-1b914128\/\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2022\/03\/cropped-Isotipo-Bluetab-150x150.png\" alt=\"\" loading=\"lazy\"><\/a><\/figure>\n<h4><a href=\"https:\/\/www.linkedin.com\/in\/roberto-garc%C3%ADa-parra-1b914128\/\" target=\"_blank\" rel=\"noopener\">Roberto Garc\u00eda Parra<\/a><\/h4>\n<p>Technical Delivery Manager<\/p>\n<figure><a href=\"https:\/\/www.linkedin.com\/in\/gabriel-gallardo-ruiz-9042a0212\/\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2022\/03\/cropped-Isotipo-Bluetab-150x150.png\" alt=\"\" loading=\"lazy\"><\/a><\/figure>\n<h4><a href=\"https:\/\/www.linkedin.com\/in\/gabriel-gallardo-ruiz-9042a0212\/\" target=\"_blank\" rel=\"noopener\">Gabriel Gallardo Ruiz<\/a><\/h4>\n<p>Senior Data Architect<\/p>\n<h2>Introducci\u00f3n a Snowflake<\/h2>\n<p>Este art\u00edculo supone una continuaci\u00f3n del art\u00edculo inicial que hicimos sobre el almacenamiento en Snowflake, y ser\u00e1 el primero de una serie donde entraremos a fondo en las caracter\u00edsticas m\u00e1s diferenciadoras de Snowflake. El primer art\u00edculo se puede consultar <a href=\"https:\/\/bluetab.net\/guia-avanzada-sobre-almacenamiento-en-snowflake\/\">aqu\u00ed.<\/a><\/p>\n<p>Recordar que <b>una de las caracter\u00edsticas principales del almacenamiento en Snowflake es la inmutabilidad de los archivos<\/b>: Cuando hay una operaci\u00f3n DML sobre una tabla, los ficheros donde est\u00e1n los datos nunca se modifican, sino que se van creando nuevas versiones de los mismos, archivando todas las versiones anteriores por las que han ido pasando los ficheros durante el tiempo de retenci\u00f3n establecido en el par\u00e1metro DATA_RETENTION_TIME_IN_DAYS par\u00e1metro que se puede establecer a nivel base de datos, esquema o tabla.<\/p>\n<p>Este archivado es lo que posibilita las <b>dos funcionalidades avanzadas de Snowflake<\/b> que se van a ver en este art\u00edculo:<b> El Time Travel y el Fail-Safe.<\/b><\/p>\n<h2>\u00bfQu\u00e9 es el Time Travel?<\/h2>\n<p>El Time Travel es una <b>funcionalidad que permite acceder a versiones hist\u00f3ricas por las que han ido pasando los datos en las tablas<\/b>. Por ejemplo, si tenemos un proceso de carga diaria de una tabla de movimientos contables, podr\u00edamos lanzar una consulta de cu\u00e1l era el estado de los movimientos contables tres d\u00edas atr\u00e1s.<\/p>\n<h2>\u00bfQu\u00e9 es el Fail-Safe?<\/h2>\n<p>Es <b>un periodo adicional de siete d\u00edas por el que Snowflake almacena las versiones de los datos para una posible recuperaci\u00f3n<\/b>. Este periodo no es configurable, siempre es de siete d\u00edas, y \u00fanicamente aplica en un tipo de tablas: Las permanentes.&nbsp;<\/p>\n<p>Los objetos con Fail-Safe son las bases de datos, esquemas y tablas.<\/p>\n<h2>\u00bfQu\u00e9 se puede hacer con el Time Travel?<\/h2>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Consultar una foto est\u00e1tica de cualquier momento del pasado hasta un m\u00e1ximo de 90 d\u00edas. Por ejemplo, de una tabla de movimientos contables, podr\u00edamos sacar un balance con los movimientos congelados a una fecha.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Recuperar tablas que se hayan borrado accidentalmente de forma muy sencilla mediante un simple comando SQL (UNDROP).<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Recovery point-in-time: Recuperar datos en un punto concreto, dentro del plazo de los 90 d\u00edas m\u00e1ximo del time travel.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Poder sacar snapshots de los datos para guardarlos permanentemente \u2192 Para esto podr\u00edamos combinar dos funcionalidades: El time travel y el zero-copy cloning, que veremos m\u00e1s adelante.<\/li>\n<\/ul>\n<h2>\u00bfC\u00f3mo utilizar el Fail-Safe?<\/h2>\n<p><b>El Fail-Safe permite recuperar datos hasta siete d\u00edas m\u00e1ximo despu\u00e9s de la expiraci\u00f3n del Time Travel<\/b>. Esta recuperaci\u00f3n solamente puede ser hecha a trav\u00e9s del equipo de soporte de Snowflake, a diferencia del Time Travel, y se debe hacer v\u00eda petici\u00f3n. <b>El Fail-Safe es un mecanismo para poder recuperar datos en caso de emergencia, <\/b>no est\u00e1 pensado para hacer queries hist\u00f3ricas, etc. para eso hay que usar el Time Travel.<\/p>\n<p>No hay un SLA asociado a la recuperaci\u00f3n de datos en Fail-Safe: Snoflake habla de horas incluso d\u00edas para recuperar estos datos.<\/p>\n<h2>\u00bfC\u00f3mo se configura el Time Travel?<\/h2>\n<p>Es un servicio que nos proporciona Snowflake y <b>no hay que hacer nada adicional<\/b>, m\u00e1s all\u00e1 de configurar el n\u00famero de d\u00edas que queremos que nuestros objetos lo tengan activo. Hay que tener en cuenta lo siguiente:<\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Dependiendo de la edici\u00f3n que tengamos contratada de Snowflake, el n\u00famero de d\u00edas permitido de Time Travel puede diferir. A d\u00eda de hoy, en la edici\u00f3n Standard solamente se puede habilitar hasta un d\u00eda de Time Travel, mientras que a partir de la edici\u00f3n Enterprise podemos habilitar hasta 90 d\u00edas de Time Travel.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\">El Time Travel de hasta 90 d\u00edas solamente est\u00e1 habilitado en las tablas permanentes. Resto de tablas, un d\u00eda m\u00e1ximo de Time Travel. Si quieres saber m\u00e1s sobre los tipos de tablas, hablamos sobre ellas en nuestro anterior <a href=\"https:\/\/bluetab.net\/guia-avanzada-sobre-almacenamiento-en-snowflake\/\">art\u00edculo<\/a> sobre almacenamiento, en la secci\u00f3n DML\u2019s en Snowflake. El par\u00e1metro que configura el n\u00famero de d\u00edas de Time Travel en las tablas es el DATA_RETENTION_TIME_IN_DAYS. Este valor est\u00e1 por defecto a 1, pero podemos especificar un valor distinto a nivel base de datos o esquema, para que todos los objetos por debajo hereden dicho valor. Tambi\u00e9n es posible configurar un tiempo m\u00ednimo de retenci\u00f3n a nivel de cuenta, mediante el par\u00e1metro MIN_DATA_RETENTION_TIME_IN_DAYS. Este par\u00e1metro solamente es configurable por el rol ACCOUNTADMIN, y en caso de tener un valor, el tiempo de retenci\u00f3n de una tabla ser\u00eda el m\u00e1ximo del valor MIN_DATA_RETENTION_TIME_IN_DAYS a nivel cuenta y el DATA_RETENTION_TIME_IN_DAYS de la propia tabla.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Si queremos deshabilitar el TIME TRAVEL, simplemente tenemos que establecer un valor cero al par\u00e1metro DATA_RETENTION_TIME_IN_DAYS.<\/li>\n<\/ul>\n<h2>\u00bfC\u00f3mo se configura el Fail-Safe?<\/h2>\n<p><b>El Fail-Safe no es configurable<\/b>. Es un <b>periodo fijo de siete d\u00edas<\/b> que se activa autom\u00e1ticamente en tablas permanentes sin necesidad de intervenci\u00f3n alguna por parte del usuario, una vez que finaliza el periodo de Time Travel, o si se reduce este periodo, y hay datos con antig\u00fcedad superior al nuevo periodo definido, los cuales pasar\u00edan tambi\u00e9n autom\u00e1ticamente a Fail-Safe.<\/p>\n<h2>Consideraciones a tener en cuenta en el Time Travel y el Fail-Safe<\/h2>\n<h3><strong>\u00bfEs posible modificar el Time Travel de un objeto?<\/strong><\/h3>\n<p>S\u00ed, es posible, pero hay que tener en cuenta el impacto que tiene dicha modificaci\u00f3n:<\/p>\n<ul>\n<li><b>Si se incrementa<\/b>, la extensi\u00f3n solamente afecta a datos que est\u00e9n archivados en ese momento, no as\u00ed a datos que ya hayan pasado a Fail-Safe. Imaginemos que tenemos una tabla con un Time-Travel de 5 d\u00edas y la modificamos a 10 d\u00edas, los datos dentro de los 5 d\u00edas s\u00ed se les extender\u00eda su periodo a 10, pero los datos con una antig\u00fcedad mayor a 5 d\u00edas que hayan pasado al Fail-Safe, seguir\u00edan en el Fail-Safe, incluso si solo ha pasado por ejemplo un d\u00eda desde que est\u00e1n en el Fail-Safe.<\/li>\n<li aria-level=\"1\"><b>Si se disminuye, <\/b>solamente los datos dentro del nuevo periodo de Time Travel permanecen ah\u00ed, mientras que el resto pasa a Fail-Safe. Si reducimos por ejemplo de 20 d\u00edas a dos d\u00edas, solamente se mantendr\u00e1n los datos que se hayan generado en estos \u00faltimos dos d\u00edas, mientras que los datos con antig\u00fcedad mayor o igual a 3 d\u00edas pasan a Fail-Safe.<\/li>\n<\/ul>\n<p>La modificaci\u00f3n del Time Travel de un objeto se hace mediante una sentencia ALTER TABLE, modificando el par\u00e1metro DATA_RETENTION_TIME_IN_DAYS al nuevo tiempo en d\u00edas deseado.<\/p>\n<h3><strong>\u00bfQu\u00e9 pasa cuando el periodo de retenci\u00f3n de un contenedor y un objeto chocan y el contenedor es borrado?<\/strong><\/h3>\n<p>El contenedor se refiere a un objeto Snowflake que a su vez contiene 1..n objetos. Dos claros ejemplos son una base de datos, que a su vez contiene 1..n esquemas, y un esquema que a su vez contiene 1..n objetos de esquema tales como tablas, vistas o procedimientos almacenados entre otros.<\/p>\n<p>Cuando una base de datos o esquema tiene definido un periodo de retenci\u00f3n, y los objetos hijos tienen definidos un periodo de retenci\u00f3n propio, cuando se borra el contenedor padre todo lo que est\u00e9 contenido se retiene por el periodo definido en el padre, incluso si algunos de los objetos hijo tiene su propio periodo de retenci\u00f3n y es diferente al del padre.<\/p>\n<p>Esto quiere decir que si tenemos una base de datos con un periodo de retenci\u00f3n de 5 d\u00edas, y uno de los esquemas contenidos tiene definido un periodo de 10 d\u00edas, si hay un borrado de la base de datos solamente tendr\u00edamos 5 d\u00edas para recuperar no solo la base de datos sino tambi\u00e9n cualquiera de los esquemas. Esto aplica tambi\u00e9n a cuando tenemos un periodo de retenci\u00f3n a nivel de objetos, y borramos el esquema que los contiene. En ese caso, el periodo de retenci\u00f3n que cuenta siempre es el del esquema.<\/p>\n<p>Si se desea mantener un periodo de retenci\u00f3n diferente para alguno de los hijos, estos deben ser borrados previamente a la eliminaci\u00f3n del contenedor. Por ejemplo, se borran primero las tablas en las que quiero mantener su periodo propio de retenci\u00f3n, y posteriormente se borra el esquema.<\/p>\n<h2>Costes del Time Travel y el Fail-Safe<\/h2>\n<p>El Time Travel y el Fail Safe aumentan nuestra factura de almacenamiento. Todas las versiones hist\u00f3ricas que se vayan archivando de nuestros datos, ocupan un almacenamiento que tendremos que pagar, aunque hay que tener en cuenta que Snowflake, c\u00f3mo vimos en el art\u00edculo de almacenamiento, gestiona esto de la manera m\u00e1s eficiente posible, con lo que si por ejemplo, modificamos datos que afectan a una \u00fanica micropartici\u00f3n, solo esta micropartici\u00f3n es archivada, pero no archivar\u00eda microparticiones no afectadas por la modificaci\u00f3n.<\/p>\n<p><b>Hay que tener cuidado en los siguientes supuestos<\/b>, que sobre todo en tablas de alto volumen, pueden incrementar considerablemente los costes:<\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Truncados-borrados e inserciones continuos en tablas de alto volumen<\/b>. Imaginemos que tenemos una tabla de varios gigas, que continuamente borramos y volvemos a cargar. En estos casos, cada vez que hici\u00e9ramos esa operaci\u00f3n de borrado-inserci\u00f3n, estar\u00edamos archivando varios gigas de tabla, y eso si se multiplica varias veces por el n\u00famero de d\u00edas, puede ser importante en la factura.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Actualizaciones masivas de datos con frecuencia<\/b>. Imaginemos que tenemos un proceso que actualiza una columna despu\u00e9s de cada inserci\u00f3n. Esto tambi\u00e9n generar\u00eda el archivado de toda la tabla entera.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\"><b>Drops de tablas<\/b>. Por el mismo motivo que un truncate, esto genera que se archive la tabla completa. Si hacemos continuos drops y recreaciones de la tabla con datos nuevos, una tabla permanente puede disparar los costes de almacenamiento.<\/li>\n<\/ul>\n<p><b>Se recomienda para controlar los costes derivados del Time Travel y el Fail-Safe lo siguiente<\/b>:<\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Si tenemos tablas que son f\u00e1cilmente reproducibles desde fuera de Snowflake, mejor utilizar tablas transitorias que permanentes. De esta manera, nos ahorraremos los siete d\u00edas de Fail-Safe y como m\u00e1ximo tendremos un d\u00eda de Time Travel. Por ejemplo, tablas de lookup, o tablas de apoyo-staging para ciertos procesos ETL\u2019s que no son esenciales. En este \u00faltimo caso, si no es necesario que la tabla persista m\u00e1s all\u00e1 de la vida de la sesi\u00f3n, se puede configurar incluso como tabla temporal y ahorrar m\u00e1s, ya que en cuanto termina la sesi\u00f3n la tabla desaparece y no se puede recuperar.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Las tablas de hechos normalmente deber\u00edan ser tablas permanentes, pero si de igual manera las podemos recuperar f\u00e1cilmente desde el sistema origen en caso de desastre, nos podemos plantear generar algunas como transitorias, y sacar backups peri\u00f3dicos con zero-copy cloning, caracter\u00edstica que tambi\u00e9n se desarrollar\u00e1 en este art\u00edculo.<\/li>\n<\/ul>\n<h2>\u00bfC\u00f3mo utilizar el Time Travel? Casos de uso pr\u00e1cticos<\/h2>\n<p>En nuestro ejemplo, tenemos una tabla donde se carga un stock diario. Lo que hemos hecho, ha sido el d\u00eda 10 de noviembre cargar el stock de esa fecha, y el d\u00eda 11 de noviembre hemos machacado el stock del 10 de noviembre por el actual a 11 de noviembre. Fijamos un Time Travel de treinta d\u00edas a nivel base de datos (que es el que aplicar\u00eda por defecto a los objetos por debajo). Pasan 19 d\u00edas desde la \u00faltima carga.<\/p>\n<p><b>Casos de uso que se plantean<\/b>:<\/p>\n<ul>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Un usuario quiere recuperar mediante una consulta la foto del 10 de noviembre.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Por error, uno de nuestros analistas borr\u00f3 la tabla. Es necesario recuperar el stock que ten\u00edamos de producto lo m\u00e1s r\u00e1pido posible.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Un usuario nos pide que guardemos una foto del estado del stock a 10 de noviembre, por si nos lo piden en alguna auditor\u00eda.<\/li>\n<li style=\"font-weight: 400;\" aria-level=\"1\">Un analista necesita actualizar el stock de un producto concreto en el d\u00eda 11 de noviembre, pero se equivoca y actualiza todos los productos. Restaurar la tabla al punto de antes del error.<\/li>\n<\/ul>\n<p>Partimos ya de un stage interno creado en Snowflake donde hemos volcado los ficheros del 10 y el 11 de noviembre, y lanzamos el COPY INTO para insertarlos en la tabla cada d\u00eda.<\/p>\n<h2><strong>Primer caso de uso: Consulta de un estado anterior de la tabla<\/strong><\/h2>\n<p>Si hacemos una consulta sobre la tabla, lo que obtenemos es el stock a d\u00eda 11 de noviembre:<\/p>\n<p><img decoding=\"async\" width=\"977\" height=\"375\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel1.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel1.png 977w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel1-300x115.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel1-768x295.png 768w\" sizes=\"(max-width: 977px) 100vw, 977px\"><\/p>\n<p>Para el usuario poder consultar la informaci\u00f3n a 10 de noviembre en esta tabla, tendr\u00eda tres opciones:<\/p>\n<ul>\n<li>Consulta con un timestamp fijo. Es decir, consultamos la tabla tal cual estaba en un momento espec\u00edfico del tiempo. En nuestro caso, la consultamos a 10 de noviembre:<\/li>\n<\/ul>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"872\" height=\"329\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel2.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel2.png 872w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel2-300x113.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel2-768x290.png 768w\" sizes=\"(max-width: 872px) 100vw, 872px\"><figcaption><\/figcaption><\/figure>\n<ul>\n<li>Mediante un offset en segundos. Aqu\u00ed lo que hacemos es decir que queremos consultar la informaci\u00f3n al estado de hace 19 d\u00edas (cuando hacemos la consulta es 29 de noviembre, y queremos los datos del 10 de noviembre). Para ir 19 d\u00edas hacia atr\u00e1s, como el offset es en segundos, multiplicamos 60*60*24 (con esto pasamos los segundos a d\u00edas) y por 19 (que son los d\u00edas que queremos viajar hacia atr\u00e1s):<\/li>\n<\/ul>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"977\" height=\"268\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel3.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel3.png 977w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel3-300x82.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel3-768x211.png 768w\" sizes=\"(max-width: 977px) 100vw, 977px\"><figcaption><\/figcaption><\/figure>\n<ul>\n<li>Con un ID de query. Ojo con esta opci\u00f3n porque tambi\u00e9n puede dar problemas. En nuestro caso, cuando la ejecutamos, da el siguiente error:<\/li>\n<\/ul>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"891\" height=\"460\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel4.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel4.png 891w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel4-300x155.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel4-768x396.png 768w\" sizes=\"(max-width: 891px) 100vw, 891px\"><figcaption><\/figcaption><\/figure>\n<p>Nos cercioramos de que ese ID de query s\u00ed que existe en el historial completo (Base de datos SNOWFLAKE, esquema ACCOUNT_USAGE, tabla QUERY_HISTORY:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"977\" height=\"268\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel5.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel5.png 977w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel5-300x82.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel5-768x211.png 768w\" sizes=\"(max-width: 977px) 100vw, 977px\"><figcaption><\/figcaption><\/figure>\n<p>Vemos que el ID es correcto y es justo cuando hicimos el truncate de la tabla para borrar los datos del d\u00eda 10. El motivo por el que creemos que viene el error es porque el detalle del historial de queries solamente se guarda durante 14 d\u00edas, con lo cual, este m\u00e9todo no es recomendable para lanzar consultas pasado este periodo. Aunque nuestro Time Travel sea mayor (como en este caso, 30 d\u00edas) el detalle de datos de la query no es accesible.<\/p>\n<h2>Segundo caso de uso: Recuperaci\u00f3n de una tabla borrada por error<\/h2>\n<p>Imaginemos que alg\u00fan usuario de manera accidental borra del todo la tabla:<\/p>\n<p><strong><em>drop table stock_diario<\/em><\/strong><\/p>\n<p>Los usuarios empiezan a quejarse que hay aplicaciones que han dejado de funcionar, tardar\u00edamos bastante tiempo en reprocesar el archivo en origen, dependemos de un equipo que nos lo haga\u2026<\/p>\n<p>Snowflake facilita la recuperaci\u00f3n de una tabla borrada durante el tiempo del Time Travel con una simple instrucci\u00f3n. Undrop la cual al ser una operaci\u00f3n de metadata se ejecuta inmediatamente. No es necesario tener que localizar un backup donde estaba esa tabla ok, restaurarlo, sacar la tabla\u2026 simplemente ejecutar esta sentencia.<\/p>\n<p>Demostraci\u00f3n a continuaci\u00f3n, borramos la tabla:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"393\" height=\"37\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel6.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel6.png 393w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel6-300x28.png 300w\" sizes=\"(max-width: 393px) 100vw, 393px\"><figcaption><\/figcaption><\/figure>\n<p>Ejecutamos una query y nos devuelve el siguiente error:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"658\" height=\"208\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel7.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel7.png 658w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel7-300x95.png 300w\" sizes=\"(max-width: 658px) 100vw, 658px\"><figcaption><\/figcaption><\/figure>\n<p>Ejecutamos la sentencia undrop:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"666\" height=\"289\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel8.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel8.png 666w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel8-300x130.png 300w\" sizes=\"(max-width: 666px) 100vw, 666px\"><figcaption><\/figcaption><\/figure>\n<p>Y vemos que Snowflake nos devuelve el mensaje de que la tabla ha sido correctamente restaurada.<\/p>\n<p>Y comprobamos que podemos volver a hacer queries. Por supuesto, el Time Travel despu\u00e9s de la recuperaci\u00f3n se mantiene, pudiendo tambi\u00e9n consultar fotos anteriores de la tabla tal y como vemos en la captura:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"977\" height=\"252\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel9.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel9.png 977w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel9-300x77.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel9-768x198.png 768w\" sizes=\"(max-width: 977px) 100vw, 977px\"><figcaption><\/figcaption><\/figure>\n<p>Importante a tener en cuenta: El UNDROP siempre restaura la \u00faltima versi\u00f3n de los datos que hubiese en el momento del borrado.<\/p>\n<h2>Tercer caso de uso: Sacar una foto est\u00e1tica de un estado de la tabla<\/h2>\n<p>Ya se ha visto que durante el periodo de Time Travel podemos consultar el estado anterior de una tabla. Pero, \u00bfy si un usuario pidiera guardar el estado de esa tabla de forma permanente? Este caso de uso es frecuente en el mundo financiero y de la auditor\u00eda para cosas tales como poder sacar un estado de cuentas con los movimientos a una determinada fecha, o que un regulador nos pida sacar instant\u00e1neas de los datos a determinados momentos para una consulta posterior.<\/p>\n<p>La opci\u00f3n m\u00e1s inmediata para satisfacer este requerimiento ser\u00eda combinar las funcionalidades de zero-copy cloning y time travel. Las ventajas que nos ofrece esta opci\u00f3n ser\u00eda:<\/p>\n<ul>\n<li>No duplicamos almacenamiento por la instant\u00e1nea. Durante el tiempo de Time Travel, tenemos un \u00fanico fichero, y nuestro clon apuntar\u00eda a esa versi\u00f3n de los datos. Cuando el Time Travel expire, Snowflake sabr\u00e1 que hay un clon apuntando a esos datos y por tanto no los borrar\u00e1. Si lo hici\u00e9semos insertando los datos en una nueva tabla, durante el Time Travel de esa versi\u00f3n de los datos se estar\u00eda duplicando el almacenamiento.<\/li>\n<li>Creamos todo en una simple sentencia.<\/li>\n<\/ul>\n<p>A continuaci\u00f3n se muestra el clonado de nuestra tabla de stock con la foto del 10 de noviembre:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"977\" height=\"295\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel10.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel10.png 977w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel10-300x91.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel10-768x232.png 768w\" sizes=\"(max-width: 977px) 100vw, 977px\"><figcaption><\/figcaption><\/figure>\n<p>Imaginemos que pasa el time travel de esta tabla. Podemos simularlo haciendo un ALTER TABLE y poniendo la tabla a 10 d\u00edas (han pasado m\u00e1s de 10 d\u00edas desde la \u00faltima modificaci\u00f3n):<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"756\" height=\"47\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel11.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel11.png 756w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel11-300x19.png 300w\" sizes=\"(max-width: 756px) 100vw, 756px\"><figcaption><\/figcaption><\/figure>\n<p>Si se intenta sacar la foto a 10 de Noviembre desde la tabla original, Snowflake devuelve el siguiente error:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"977\" height=\"70\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel12.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel12.png 977w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel12-300x21.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel12-768x55.png 768w\" sizes=\"(max-width: 977px) 100vw, 977px\"><figcaption><\/figcaption><\/figure>\n<p>Ya que ese estado de los datos ten\u00edan una antig\u00fcedad mayor a 10 d\u00edas, Snowflake lo ha llevado directamente a Fail-Safe.<\/p>\n<p>Si consultamos el clon que se acaba de generar:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"977\" height=\"266\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel13.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel13.png 977w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel13-300x82.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel13-768x209.png 768w\" sizes=\"(max-width: 977px) 100vw, 977px\"><figcaption><\/figcaption><\/figure>\n<p>Se ve que a pesar de que el Time Travel ha expirado, mantenemos la foto del 10 de noviembre, y esta foto persistir\u00e1 salvo que borremos el clon.<\/p>\n<h2>Cuarto caso de uso: Restaurar la tabla a un estado anterior<\/h2>\n<p>Imaginemos que le piden a un usuario actualizar el stock de impresoras de 15 a 14 unidades. Para ello el usuario genera la siguiente consulta:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"356\" height=\"108\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel14.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel14.png 356w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel14-300x91.png 300w\" sizes=\"(max-width: 356px) 100vw, 356px\"><figcaption><\/figcaption><\/figure>\n<p>El usuario se ha olvidado de un peque\u00f1o detalle y es aplicar un where para \u00fanicamente actualizar la l\u00ednea de las impresoras, con lo que ahora todo el stock est\u00e1 a 14 unidades de forma err\u00f3nea.<\/p>\n<p>Para recuperar la tabla, podr\u00edamos recrearla gracias al Time Travel, mediante una sentencia create or replace:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"797\" height=\"164\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel15.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel15.png 797w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel15-300x62.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel15-768x158.png 768w\" sizes=\"(max-width: 797px) 100vw, 797px\"><figcaption><\/figcaption><\/figure>\n<p>Lo que estamos haciendo es sustituir la tabla al estado al que estaba ayer (que es el correcto).<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"977\" height=\"270\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel16.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel16.png 977w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel16-300x83.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel16-768x212.png 768w\" sizes=\"(max-width: 977px) 100vw, 977px\"><figcaption><\/figcaption><\/figure>\n<p><strong>IMPORTANTE<\/strong>: Hay que tener en cuenta que cuando hacemos un REPLACE TABLE como en este caso, se genera una nueva tabla con una metadata limpia, con lo cual perdemos el Time Travel en esa tabla. Si por ejemplo, intentamos recuperar la informaci\u00f3n 5 minutos atr\u00e1s, nos dir\u00e1 que no hay Time Travel de ese momento:<\/p>\n<figure>\n\t\t\t\t\t\t\t\t\t\t<img decoding=\"async\" width=\"977\" height=\"79\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel17.png\" alt=\"\" loading=\"lazy\" srcset=\"https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel17.png 977w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel17-300x24.png 300w, https:\/\/bluetab.net\/wp-content\/uploads\/2023\/02\/time-travel17-768x62.png 768w\" sizes=\"(max-width: 977px) 100vw, 977px\"><figcaption><\/figcaption><\/figure>\n<p>Cuando hagamos estas restauraciones debemos estar muy seguros. Una opci\u00f3n recomendable ser\u00eda antes de machacar la tabla original, hacer el replace en una tabla nueva y revisar que todo est\u00e9 ok.<\/p>\n<h2>Conclusiones<\/h2>\n<p><strong>El Time Travel y el Fail-Safe son dos funcionalidades que nos proporciona Snowflake sin tener que mantener ni configurar pr\u00e1cticamente nada, <\/strong>y que cubren gran cantidad de casos de uso c\u00f3mo consultas de hist\u00f3rico, recuperaci\u00f3n r\u00e1pida en caso de error o problema y la posibilidad de sacar instant\u00e1neas a un momento determinado en combinaci\u00f3n con el zero-copy cloning.<\/p>\n<p>Es importante tener muy claro los tiempos de retenci\u00f3n de cada una de las bases de datos-esquemas tablas, y seleccionar el tipo de tabla adecuado en consecuencia, para optimizar al m\u00e1ximo el coste de almacenamiento.<\/p>\n<h6><strong>Navegaci\u00f3n<\/strong><\/h6>\n<p><a href=\"\/#intro\">Introducci\u00f3n<\/a><\/p>\n<p><a href=\"\/#objetivo\">\u00bfQu\u00e9 es el Time Travel?<br \/>\n<\/a><\/p>\n<p><a href=\"\/#escalabilidad\">\u00bfQu\u00e9 es el Fail-Safe?<br \/>\n<\/a><\/p>\n<p><a href=\"\/#objetivosal\">\u00bfQu\u00e9 se puede hacer con el Time Travel?<\/a><\/p>\n<p><a href=\"\/#principalal\">\u00bfC\u00f3mo utilizar el Fail-Safe?<br \/>\n<\/a><\/p>\n<p><a href=\"\/#metacatos\">\u00bfC\u00f3mo se configura el Time Travel?<br \/>\n<\/a><\/p>\n<p><a href=\"\/#principalmicro\">\u00bfC\u00f3mo se configura el Fail-Safe?<br \/>\n<\/a><\/p>\n<p><a href=\"\/#entendiendo\">Consideraciones a tener en cuenta en el Time Travel y el Fail-Safe<br \/>\n<\/a><\/p>\n<p><a href=\"\/#dml\">Costes del Time Travel y el Fail-Safe<br \/>\n<\/a><\/p>\n<p><a href=\"\/#aspectos\">\u00bfC\u00f3mo utilizar el Time Travel? Casos de uso pr\u00e1cticos<\/a><\/p>\n<p><a href=\"\/#conclusiones\">Principales conclusiones<\/a><\/p>\n<p><a href=\"\/#autores\">Autores<\/a><\/p>\n<h5>\u00bfQuieres saber m\u00e1s de lo que ofrecemos y ver otros casos de \u00e9xito?<\/h5>\n<p><a href=\"\/\" role=\"button\"><br \/>\nDESCUBRE BLUETAB<br \/>\n<\/a><\/p>\n<figure><a href=\"https:\/\/www.linkedin.com\/in\/roberto-garc%C3%ADa-parra-1b914128\/\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2022\/03\/cropped-Isotipo-Bluetab-150x150.png\" alt=\"\" loading=\"lazy\"><\/a><\/figure>\n<h4><a href=\"https:\/\/www.linkedin.com\/in\/roberto-garc%C3%ADa-parra-1b914128\/\" target=\"_blank\" rel=\"noopener\">Roberto Garc\u00eda Parra<\/a><\/h4>\n<p>Technical Delivery Manager<\/p>\n<figure><a href=\"https:\/\/www.linkedin.com\/in\/gabriel-gallardo-ruiz-9042a0212\/\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" width=\"150\" height=\"150\" src=\"https:\/\/bluetab.net\/wp-content\/uploads\/2022\/03\/cropped-Isotipo-Bluetab-150x150.png\" alt=\"\" loading=\"lazy\"><\/a><\/figure>\n<h4><a href=\"https:\/\/www.linkedin.com\/in\/gabriel-gallardo-ruiz-9042a0212\/\" target=\"_blank\" rel=\"noopener\">Gabriel Gallardo Ruiz<\/a><\/h4>\n<p>Senior Data Architect<\/p>\n<p><b>SOLUCIONES, <\/b>SOMOS EXPERTOS<\/p>\n<p><a href=\"\/soluciones\/data-strategy\/\"><\/a><\/p>\n<p><a href=\"\/soluciones\/data-strategy\/\"><\/p>\n<h5>DATA STRATEGY<\/h5>\n<p><\/a><a href=\"\/soluciones\/data-strategy\/\">\t\t\t\t\t\t<\/a><br \/>\n<a href=\"\/soluciones\/data-fabric\/\"><\/a><\/p>\n<p><a href=\"\/soluciones\/data-fabric\/\"><\/p>\n<h5>DATA FABRIC<\/h5>\n<p><\/a><a href=\"\/soluciones\/data-fabric\/\">\t\t\t\t\t\t<\/a><br \/>\n<a href=\"\/soluciones\/augmented-analytics\/\"><\/a><\/p>\n<p><a href=\"\/soluciones\/augmented-analytics\/\"><\/p>\n<h5>AUGMENTED ANALYTICS<\/h5>\n<p><\/a><a href=\"\/soluciones\/augmented-analytics\/\">\t\t\t\t\t\t<\/a><\/p>\n<p>Te puede interesar<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Snowflake, el Time Travel sin DeLorean para unos datos Fail-Safe. Roberto Garc\u00eda Parra Technical Delivery Manager Gabriel Gallardo Ruiz Senior Data Architect Introducci\u00f3n a Snowflake Este art\u00edculo supone una continuaci\u00f3n del art\u00edculo inicial que hicimos sobre el almacenamiento en Snowflake, y ser\u00e1 el primero de una serie donde entraremos a fondo en las caracter\u00edsticas m\u00e1s [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":20823,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"elementor_header_footer","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7,29,30],"tags":[],"class_list":["post-14735","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-es","category-practices-en","category-tech-en"],"acf":[],"jetpack_featured_media_url":"https:\/\/bluetab.es\/wp-content\/uploads\/2023\/03\/8.png","_links":{"self":[{"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/posts\/14735","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/comments?post=14735"}],"version-history":[{"count":0,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/posts\/14735\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/media\/20823"}],"wp:attachment":[{"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/media?parent=14735"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/categories?post=14735"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bluetab.es\/en\/wp-json\/wp\/v2\/tags?post=14735"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}