Présentation de l’actualisation des tables dynamiques¶
Le contenu d’une table dynamique est basé sur les résultats d’une requête spécifique. Lorsque les données sous-jacentes sur lesquelles la table dynamique est basée changent, la table est mise à jour pour refléter ces changements. Ces mises à jour sont appelées actualisations. Ce processus est automatisé et consiste à analyser la requête qui sous-tend la table.
Les délais d’expiration de l’actualisation des tables dynamiques sont déterminés par le paramètre STATEMENT_TIMEOUT_IN_SECONDS, qui définit la durée maximale sur le compte ou dans l’entrepôt avant l’annulation automatique.
Les sections suivantes expliquent plus en détail l’actualisation des tables dynamiques :
Requêtes prises en charge dans le cadre de l’actualisation incrémentielle
Fonctions non déterministes prises en charge dans le cadre d’une actualisation complète
Modes d’actualisation des tables dynamiques¶
Le processus d’actualisation d’une table dynamique se déroule de deux manières :
Actualisation incrémentielle : ce processus automatisé analyse la requête de la table dynamique et calcule les changements survenus depuis la dernière actualisation. Il fusionne ensuite ces modifications dans la table. Voir Requêtes prises en charge dans le cadre de l’actualisation incrémentielle pour plus de détails sur les requêtes prises en charge.
Actualisation complète : Lorsque le processus automatisé ne peut pas effectuer une actualisation incrémentielle, il effectue une actualisation complète. Cela implique l’exécution de la requête pour la table dynamique et le remplacement complet des résultats matérialisés précédents.
Les constructions utilisées dans la requête déterminent si une actualisation incrémentielle peut être utilisée. Après avoir créé une table dynamique, vous pouvez surveiller la table pour déterminer si des actualisations incrémentielles ou complètes sont utilisées pour mettre à jour cette table.
Comprendre la latence cible¶
L’actualisation des tables dynamiques est déclenchée en fonction du degré d’obsolescence des données, ce que l’on appelle communément latence cible. La latence cible d’une table dynamique est mesurée par rapport aux tables de base situées à la racine du graphique et non par rapport aux tables dynamiques situées directement en amont. Snowflake planifie les actualisations de manière à ce que la latence réelle de vos tables dynamiques reste inférieure à la latence cible. La durée de chaque actualisation dépend de la requête, du modèle de données et de la taille de l’entrepôt. Lorsque vous choisissez une latence cible, tenez compte du temps nécessaire pour actualiser chaque table dynamique dans une chaîne jusqu’à la racine. Si vous ne le faites pas, certaines actualisations risquent d’être ignorées, ce qui entraînera une latence plus importante.
Pour voir le graphique des tables liées à votre table dynamique, voir Utiliser Snowsight pour examiner le graphique des tables dynamiques.
La latence cible est spécifiée de l’une des manières suivantes :
Mesure du niveau d’actualisation : spécifie le délai maximum pendant lequel le contenu de la table dynamique doit être décalé par rapport aux mises à jour des tables de base.
L’exemple suivant configure la table dynamique
product
pour qu’elle soit actualisée et conserve son niveau d’actualisation toutes les heures :ALTER DYNAMIC TABLE product SET TARGET_LAG = '1 hour';En aval : spécifie que la table dynamique doit être actualisée à la demande lorsque d’autres tables dynamiques dépendantes sont actualisées. Cette actualisation peut être déclenchée par une actualisation manuelle ou planifiée d’une table dynamique en aval.
Dans l’exemple suivant,
product
est basé sur d’autres tables dynamiques et est défini pour être actualisé en fonction de la latence cible de ses tables dynamiques en aval :ALTER DYNAMIC TABLE product SET TARGET_LAG = DOWNSTREAM;
La latence cible est inversement proportionnelle à la fréquence d’actualisation des tables dynamiques : des actualisations fréquentes impliquent une latence plus faible.
Prenons l’exemple suivant, dans lequel la table dynamique 2 (DT2) est définie sur la base de la table dynamique 1 (DT1). DT2 doit lire dans DT1 pour matérialiser son contenu. En outre, un rapport consomme des données DT2 par le biais d’une requête.

Les résultats suivants sont possibles, en fonction de la manière dont chaque table dynamique spécifie sa latence :
Table dynamique 1 (DT1) |
Table dynamique 2 (DT2) |
Actualiser les résultats |
---|---|---|
|
|
DT2 est mis à jour au maximum toutes les 10 minutes. DT1 déduit sa latence à partir de DT2 et est mis à jour chaque fois que DT2 demande des mises à jour. |
|
|
Ce scénario doit être évité. La requête de rapport ne recevra aucune donnée. DT 1 est fréquemment actualisé et DT2 ne l’est pas, car il n’y a pas de table dynamique basée sur DT2. |
|
|
DT2 est mis à jour environ toutes les 10 minutes avec des données provenant de DT1 et datant d’au plus 5 minutes. |
|
|
DT2 n’est pas actualisée périodiquement, car DT1 n’a pas d’enfants en aval avec une latence définie. |
Requêtes prises en charge dans le cadre de l’actualisation incrémentielle¶
La table suivante décrit les expressions, les mots-clés et les clauses qui prennent actuellement en charge l’actualisation incrémentielle. Pour une liste des requêtes qui ne prennent pas en charge l’actualisation incrémentielle, voir Limitations de la prise en charge de l’actualisation incrémentielle.
Mot-clé/Clause |
Prise en charge des actualisations incrémentielles |
---|---|
WITH |
Expressions de table communes (CTE) qui utilisent des fonctions d’actualisation incrémentielle prises en charge dans la sous-requête. |
Expressions dans SELECT |
Expressions, y compris celles qui utilisent des fonctions intégrées déterministes et des fonctions définies par l’utilisateur immuables. |
FROM |
Tables sources, vues et autres tables dynamiques. Les sous-requêtes en dehors des clauses FROM (par exemple, WHERE EXISTS) ne sont pas prises en charge. |
OVER |
Toutes les fonctions de fenêtre. |
WHERE/HAVING/QUALIFY |
Filtres avec les mêmes expressions que celles valables dans SELECT. |
JOIN (et d’autres expressions pour joindre des tables) |
Les types de jointure pris en charge pour l’actualisation incrémentielle incluent les jointures internes, les jointures d’égalité externes, les jointures croisées et les jointures aplaties latérales (uniquement la fonction de table FLATTEN non statique). Vous pouvez spécifier un nombre quelconque de tables dans la jointure, et les mises à jour de toutes les tables de la jointure sont reflétées dans les résultats de la requête. La sélection de la colonne SEQ d’aplatissement provenant d’une jointure à aplatissement latéral n’est pas prise en charge pour l’actualisation incrémentielle. |
UNION ALL |
Les tables dynamiques prennent en charge UNION ALL. |
GROUP BY |
Les tables dynamiques prennent en charge GROUP BY. |
Important
Si une requête utilise des expressions qui ne sont pas prises en charge pour l’actualisation incrémentielle, le processus d’actualisation automatisé utilise une actualisation complète, ce qui peut entraîner un coût supplémentaire. Pour déterminer le mode d’actualisation utilisé, consultez Déterminer si une actualisation incrémentielle ou complète est utilisée.
Le remplacement d’une fonction définie par l’utilisateur (UDF) IMMUTABLE alors qu’elle est utilisée par une table dynamique qui utilise l’actualisation incrémentielle entraîne un comportement indéfini dans cette table. Les UDFs VOLATILE ne sont pas prises en charge dans le cadre d’une actualisation incrémentielle.
Actuellement, les jointures latérales ne sont pas prises en charge dans le cadre d’une actualisation incrémentielle. Cependant, vous pouvez utiliser LATERAL avec FLATTEN() en définissant le mode d’actualisation sur INCREMENTAL
.
Par exemple :
CREATE TABLE persons
AS
SELECT column1 AS id, parse_json(column2) AS entity
FROM values
(12712555,
'{ name: { first: "John", last: "Smith"},
contact: [
{ business:[
{ type: "phone", content:"555-1234" },
{ type: "email", content:"j.smith@company.com" } ] } ] }'),
(98127771,
'{ name: { first: "Jane", last: "Doe"},
contact: [
{ business:[
{ type: "phone", content:"555-1236" },
{ type: "email", content:"j.doe@company.com" } ] } ] }') v;
CREATE DYNAMIC TABLE example
TARGET_LAG = DOWNSTREAM
WAREHOUSE = mywh
REFRESH_MODE = INCREMENTAL
AS
SELECT p.id, f.value, f.path
FROM persons p,
LATERAL FLATTEN(input => p.entity) f;
Note
La sélection de la colonne SEQ d’aplatissement provenant d’une jointure à aplatissement latéral n’est pas prise en charge pour l’actualisation incrémentielle.
Actualisation incrémentielle par les opérateurs¶
Le tableau suivant indique comment chaque opérateur est incrémenté (c’est-à-dire comment il est transformé en un nouveau fragment de requête qui génère des modifications au lieu de résultats complets), ainsi que ses performances et d’autres facteurs importants à prendre en compte.
Opérateur |
Incrémentation |
Considérations |
---|---|---|
SELECT <expressions scalaires> |
Incrémentation en appliquant des expressions aux lignes modifiées. |
Bonnes performances, pas de considérations particulières. |
WHERE <expressions scalaires> |
Incrémentation en évaluant le prédicat sur chaque ligne modifiée, et en n’incluant que celles pour lesquelles le prédicat est vrai. |
Les performances sont généralement bonnes. Le coût est linéairement proportionnel à l’ampleur des changements. L’actualisation d’une table dynamique à l’aide d’une expression WHERE très sélective peut nécessiter un temps de fonctionnement de l’entrepôt, même si la table dynamique résultante ne change pas. En effet, un entrepôt peut être nécessaire pour déterminer quelles modifications des sources satisfont le prédicat. |
FROM <table de base> |
Incrémenté en analysant les micro-partitions qui ont été ajoutées ou supprimées de la table depuis la dernière actualisation. |
Le coût augmente de façon linéaire avec le volume de données dans les micropartitions ajoutées ou supprimées. Recommandations :
|
<requête> UNION ALL <requête> |
Incrémentation en prenant l’union de tous les changements de chaque côté. |
Bonnes performances, pas de considérations particulières. |
WITH <CTE liste> <requête> |
Incrémentation en calculant les changements de chaque expression de table commune. |
WITH facilite la lecture des requêtes complexes, mais prenez garde à ne pas rendre trop complexe la définition d’une seule table dynamique. Pour plus d’informations, voir Lier des pipelines de tables dynamiques et Optimisation des performances du mode d’actualisation incrémentielle pour les tables dynamiques complexes. |
Agrégats scalaires |
Les agrégats scalaires ne sont actuellement pas incrémentés de manière efficace. Lorsque leurs données changent, ils sont entièrement recalculés. |
|
GROUP BY <clés> |
Incrémentation en recalculant les agrégats pour chaque clé de groupe qui a changé. |
Veillez à ce que les données sources soient mises en cluster par les clés de groupes et que les modifications ne représentent qu’une petite partie (environ <5 %) des clés de groupes. Si la clé de regroupement contient une expression composée plutôt qu’une colonne de base, les actualisations incrémentielles auront peut-être besoin d’analyser une grande quantité de données. Pour réduire la taille de ces analyses, matérialisez l’expression dans une table dynamique, puis appliquez l’opération de regroupement sur la colonne matérialisée dans une autre table dynamique. Prenons par exemple l’instruction composée suivante : CREATE DYNAMIC TABLE sums
AS
SELECT date_trunc(minute, ts), sum(c1) FROM table
GROUP BY 1;
L’instruction ci-dessus peut être optimisée comme suit : CREATE DYNAMIC TABLE intermediate
AS
SELECT date_trunc(minute, ts) ts_min, c1 FROM table;
CREATE DYNAMIC TABLE sums
AS
SELECT ts_min, sum(c1) FROM intermediate
GROUP BY 1;
|
DISTINCT |
Équivalent à GROUP BY ALL sans fonctions agrégées. |
Il s’agit souvent d’une opportunité d’optimisation substantielle. Il est courant d’utiliser DISTINCT dans toutes les requêtes afin d’éviter d’introduire accidentellement des doublons. Dans le cas d’une actualisation incrémentielle, les opérations DISTINCT consomment des ressources de manière récurrente, car les doublons doivent être vérifiés à chaque actualisation. Lorsqu’il s’agit d’optimiser les performances, il est facile de trouver et de supprimer les DISTINCTs redondants. Vous pouvez y parvenir en éliminant les doublons en amont et en examinant attentivement les cardinalités des jointures. |
<fn> OVER <fenêtre> |
Incrémentation en recalculant la fonction de fenêtre pour chaque clé de partition qui a changé. |
Assurez-vous que votre requête comporte une clause PARTITION BY et que les données sources sont mises en cluster par clés de partition. Veillez également à ce que les modifications ne concernent qu’une petite partie (environ <5 %) des partitions. |
<gauche> INNER JOIN <droite> |
Incrémentation en joignant les changements du côté gauche avec le côté droit, puis en joignant les changements du côté droit avec le côté gauche. |
Si l’un des côtés de la jonction est petit, la performance est probablement bonne. Si l’un des côtés de la jointure change fréquemment, le clustering de l’autre côté par la clé de jointure peut améliorer les performances. |
<gauche> [{LEFT | RIGHT | FULL }] OUTER JOIN <droite> |
Incrémentation par factorisation dans une jointure interne union-all-ed avec un ou deux NOT EXISTS pour calculer NULLs pour les non-correspondances. Cette requête factorisée est ensuite incrémentée. La jointure interne est incrémentée comme indiqué. Les inexistants sont incrémentés en vérifiant si les clés modifiées d’un côté existaient déjà de l’autre côté. |
Recommandations :
|
Fonctions non déterministes prises en charge dans le cadre d’une actualisation complète¶
Les fonctions non déterministes suivantes sont prises en charge dans les tables dynamiques. Notez que ces fonctions ne sont prises en charge que pour les actualisations complètes. Pour une liste des éléments non pris en charge pour l’actualisation incrémentielle, voir Limitations de la prise en charge de l’actualisation incrémentielle.
Fonctions définies par l’utilisateur VOLATILE
Fonctions séquentielles (par exemple
SEQ1
,SEQ2
)Les fonctions contextuelles suivantes :
Les fonctions de date et d’heure suivantes (ainsi que leurs alias respectifs) :
Comment les données sont-elles actualisées lorsque des tables dynamiques dépendent d’autres tables dynamiques ?¶
Lorsqu’une latence de table dynamique est spécifiée en tant que mesure de temps, le processus d’actualisation automatisé détermine le calendrier des actualisations, sur la base des temps de latence cibles des tables dynamiques. Le processus choisit un calendrier qui respecte au mieux les temps de latence cibles des tables.
Note
La latence cible n’est pas une garantie. Il s’agit plutôt d’un objectif que Snowflake tente d’atteindre. Les données des tables dynamiques sont actualisées au plus près de la latence cible. Toutefois, la latence cible peut être dépassée en raison de facteurs tels que la taille de l’entrepôt, la taille des données, la complexité des requêtes et d’autres facteurs similaires.
Afin de préserver la cohérence des données dans les cas où une table dynamique dépend d’une autre, le processus actualise toutes les tables dynamiques d’un compte à des moments compatibles. Le délai des actualisations moins fréquentes coïncide avec celui des actualisations plus fréquentes.
Par exemple, supposons qu’une table dynamique A ait un temps de latence cible de 2 minutes et qu’elle interroge une table dynamique B dont le temps de latence cible est d’une minute. Le processus peut déterminer que A doit être actualisée toutes les 96 secondes et B toutes les 48 secondes. En conséquence, le processus peut se dérouler selon le calendrier suivant :
Point précis dans le temps |
Tables dynamiques actualisées |
---|---|
2022-12-01 00:00:00 |
A, B |
2022-12-01 00:00:48 |
B |
2022-12-01 00:01:36 |
A, B |
2022-12-01 00:02:24 |
B |
Cela signifie qu’à tout moment, lorsque vous interrogez un ensemble de tables dynamiques qui dépendent les unes des autres, vous interrogez le même « instantané » des données de ces tables.
Notez que la latence cible d’une table dynamique ne peut être plus courte que la latence cible des tables dynamiques dont elle dépend. Par exemple, supposons ceci :
Une table dynamique A interroge les tables dynamiques B et C.
La table dynamique B a une latence cible de cinq minutes.
La table dynamique C a une latence cible d’une minute.
Cela signifie que le temps de latence cible pour A ne doit pas être inférieur à cinq minutes (c’est-à-dire qu’il ne doit pas être inférieur au plus long des temps de latence pour B et C).
Si vous définissez la latence pour A à cinq minutes, le processus établit un calendrier d’actualisation avec ces objectifs :
Actualisez C suffisamment souvent pour que sa latence soit inférieure à une minute.
Actualisez A et B en même temps et suffisamment souvent pour que leur latence soit inférieure à cinq minutes.
Assurez-vous que l’actualisation de A et B coïncide avec l’actualisation de C pour garantir l’isolation des instantanés.
Remarque : si les actualisations prennent trop de temps, le programmateur peut ignorer des actualisations pour essayer de rester à jour. Toutefois, l’isolation des instantanés est préservée.