Comment le mode d’actualisation affecte-t-il les performances des tables dynamiques ?¶
Le mode d’actualisation d’une table dynamique est déterminé au moment de la création et est immuable par la suite. S’il n’est pas spécifié explicitement, le mode d’actualisation est par défaut AUTO
, ce qui sélectionne un mode d’actualisation en fonction de divers facteurs tels que la complexité de la requête ou les constructions, opérateurs ou fonctions non pris en charge.
Pour vérifier le mode d’actualisation de vos tables dynamiques, consultez Afficher le mode d’actualisation de tables dynamiques.
Astuce
Pour déterminer le mode le mieux adapté à votre cas d’utilisation, expérimentez les recommandations automatiques et les modes d’actualisation concrets (actualisations complètes et incrémentielles). Le mode le plus adapté pour les performances de vos tables dynamiques dépend du volume de modification des données et de la complexité de la requête. De plus, tester différents modes d’actualisation avec un entrepôt dédié permet d’isoler les coûts et d’améliorer le réglage des performances en fonction des charges de travail réelles.
Pour un comportement cohérent entre les versions de Snowflake, définissez explicitement le mode d’actualisation sur toutes les tables de production. Le comportement de AUTO
peut changer selon les versions de Snowflake, ce qui peut entraîner des changements inattendus dans les performances s’il est utilisé dans les pipelines de production.
Pour plus d’informations, voir Meilleures pratiques pour optimiser les performances.
Performance en mode d’actualisation complète¶
Une actualisation complète exécute la requête et remplace les tables dynamiques par les résultats. Le contenu d’une table dynamique est le même, quel que le soit le mode d’actualisation choisi (actualisation complète ou incrémentielle).
L’actualisation complète est généralement utilisée pour les requêtes ou les charges de travail complexes où l’actualisation incrémentielle est moins efficace.
Bien que l’actualisation complète nécessite beaucoup de ressources, elle est utile lorsque le retraitement de l’ensemble des données est nécessaire, par exemple pour les opérations incrémentielles non prises en charge ou des modifications importantes des données.
Pour optimiser les performances de l’actualisation complète, procédez comme pour toute autre requête Snowflake, mais n’oubliez pas que le coût comprend à la fois l’exécution de la requête et l’insertion des résultats, et pas seulement l’exécution de la requête.
Performance du mode d’actualisation incrémentielle¶
Une actualisation incrémentielle se concentre sur l’application des modifications depuis la dernière actualisation, ce qui la rend plus efficace pour les grands ensembles de données avec de petites mises à jour. Le contenu d’une table dynamique est le même, quel que le soit le mode d’actualisation choisi.
Cependant, l’actualisation incrémentielle peut être plus efficace en termes de ressources, car elle évite le retraitement des données non modifiées. La décision d’utiliser l’actualisation incrémentielle dépend des caractéristiques de votre charge de travail, comme le volume et la complexité des modifications, ainsi que des gains de performances potentiels en termes de vitesse et d’économies de ressources.
La section suivante explique ce qui fait qu’une charge de travail est adaptée à l’actualisation incrémentielle. Si votre charge de travail ne correspond pas aux conditions décrites dans ces sections, essayez d’utiliser le mode d’actualisation complète pour une efficacité potentiellement meilleure.
Comprendre les performances de l’actualisation incrémentielle
Comment la taille affecte-t-elle les performances de l’actualisation incrémentielle ?
Comment la localité affecte-t-elle les performances de l’actualisation incrémentielle ?
Pour plus d’informations sur l’optimisation de la performance de l’actualisation incrémentielle, voir Performance de l’actualisation incrémentielle.
Note
Les recommandations de cette documentation sont susceptibles d’être modifiées en fonction de l’amélioration de la prise en charge des requêtes d’actualisation incrémentielle et des performances au fil du temps.
Comprendre les performances de l’actualisation incrémentielle¶
Lors d’une actualisation incrémentielle, la plupart des efforts sont généralement consacrés au calcul des modifications apportées à la table dynamique. Cela dépend de la requête et peut être assez complexe. Un malentendu courant est qu’une actualisation incrémentielle n’analyse que les modifications apportées aux tables sources, et non les tables sources elles-mêmes. Cela peut conduire à l’idée fausse qu’une actualisation incrémentielle ne doit effectuer qu’un travail proportionnel à la quantité de données source qui ont changé, ce qui n’est pas vrai. En réalité, les actualisations incrémentielles doivent souvent analyser directement les tables sources.
Par exemple, imaginez une requête qui effectue une jointure interne entre les tables A et B. Si une ligne est insérée dans la table A, elle doit être jointe à la table B pour calculer les changements dans la requête. Cette simple ligne dans A peut être jointe à de nombreuses lignes dans B, ce qui peut entraîner une charge de travail importante même si les sources ne subissent que quelques modifications.
Ce travail supplémentaire peut être effectué par différents opérateurs. L’actualisation incrémentielle traite les nouvelles données et ignore ce qui a déjà été effectué. Décider de ce qui doit être ignoré peut demander du travail supplémentaire, en particulier pour les requêtes complexes, et différents opérateurs peuvent ignorer du travail de différentes manières.
En règle générale, la taille des modifications et la localité ont une incidence sur la quantité de travail qui peut être ignorée.
Comment la taille affecte-t-elle les performances de l’actualisation incrémentielle ?¶
Le facteur le plus important qui affecte les performances de l’actualisation incrémentielle est la taille des modifications apportées aux données sources. Lorsque vous déterminez la taille des modifications pour les actualisations de vos tables dynamiques, veillez à inclure les lignes copiées dans le décompte. Une DML qui modifie certaines lignes d’une micropartition copie également les lignes inchangées de cette micropartition dans une nouvelle micropartition.
Pour analyser le nombre de lignes modifiées, dans une table de base, créez un flux dans la table de base au moment de la dernière actualisation et utilisez SYSTEM$STREAM_BACKLOG. Par exemple :
CREATE STREAM mystream ON TABLE mybasetable BEFORE(STATEMENT => 'last refresh UUID');
SELECT * FROM SYSTEM$STREAM_BACKLOG('mystream');
À titre d’exemple extrême, considérez l’effet de la suppression de toutes les données d’une source : une actualisation complète ne voit qu’une table vide, qui peut être traitée très rapidement. En revanche, une actualisation incrémentielle doit traiter chaque ligne supprimée, ce qui le rend beaucoup plus lent.
Des ralentissements similaires peuvent également se produire dans des cas moins extrêmes. Une bonne ligne de conduite pour une charge de travail favorable consiste à limiter les changements dans la source ou la cible à moins de 5 % des lignes.
Comment la localité affecte-t-elle les performances de l’actualisation incrémentielle ?¶
Le deuxième facteur le plus important qui affecte l’actualisation incrémentielle est la localité, qui fait référence à la proximité des données ou des actions en fonction de différentes dimensions.
Par exemple, si vous avez une table avec une colonne d’horodatage et que vous insérez toujours des lignes avec l’heure actuelle dans cette colonne, votre charge de travail présente une forte localité entre l’ordre d’insertion et la colonne d’horodatage.
La localité peut se manifester sous diverses formes, mais certaines sont particulièrement importantes pour l’actualisation incrémentielle. L’amélioration de la localité dans l’un des domaines suivants augmente les performances des actualisations incrémentielles, bien qu’il ne soit pas toujours possible d’obtenir une forte localité dans les trois catégories.
Zone de localité |
Description |
---|---|
Localité entre le clustering et les clés de clustering. |
Lorsque vous effectuez une opération de partitionnement dans la définition de la table dynamique, il est utile que les sources sous-jacentes soient clusterisées sur la base de ces clés de clustering. Par exemple, si vous joignez deux tables à l’aide d’une ID, il est préférable pour les performances de l’actualisation incrémentielle que les tables soient clusterisées en fonction de leurs colonnes d’ID respectives. |
Localité entre les clés de partitionnement ou de groupe et les changements de source. |
Idéalement, les modifications apportées aux sources ne devraient avoir une clé de partitionnement en commun qu’avec une petite fraction des lignes de la ou des tables sources. Par exemple, si vous insérez des lignes avec l’horodatage actuel, le regroupement par heure fonctionnerait bien en raison de la forte localité entre les clés et les changements de source. Toutefois, si vous insérez des lignes avec une valeur de colonne qui apparaît dans de nombreuses autres lignes de la table, le regroupement par cette colonne entraîne de mauvaises performances en matière d’actualisation incrémentielle. |
Localité entre les changements de table cible et le clustering. |
Lorsqu’une actualisation incrémentielle applique des modifications à une table dynamique, les mises à jour et les suppressions sont comparées à l’état actuel de la table dynamique. Cette jointure est plus performante si les changements s’alignent sur le clustering de la table dynamique. Par exemple, si les actualisations ne mettent à jour que les lignes récemment insérées, ils s’alignent bien sur le clustering de la table. Pour obtenir des informations sur la manière dont les tables Snowflake sont stockées, voir Fonctionnement des structures de table dans Snowflake. Pour gérer le clustering sur une table, utilisez Clustering automatique. |
Attentes en matière de performances pour les actualisations incrémentielles de chaque opérateur¶
Le tableau suivant indique les performances approximatives attendues pour les actualisations incrémentielles des opérateurs individuels. Les performances sont mesurées par rapport à une actualisation complète, en supposant que seulement 5 % des lignes ont été modifiées et que les tâches d’actualisation durent au moins une minute.
Note
En raison des frais généraux fixes (par exemple, l’optimisation des requêtes, la planification des entrepôts et le nettoyage des tâches) qui ne s’accélèrent pas avec l’optimisation des requêtes, les requêtes courtes (moins de 10 secondes) peuvent présenter des gains de performance plus faibles.
Opérateur |
Augmentation des performances |
---|---|
SELECT |
10x |
WHERE |
10x |
FROM |
10x |
UNION ALL |
10x |
Agrégats scalaires |
10x |
Pour les opérateurs qui sont affectés par la localité, le tableau montre les performances attendues avec une bonne et une mauvaise localité. Notez que, pour certains opérateurs, une faible localité peut conduire à de moins bonnes performances que des actualisations complètes.
Opérateur |
Localité |
Augmentation des performances |
---|---|---|
GROUP BY |
Bonne |
5x |
GROUP BY |
Mauvaise |
1/3x |
DISTINCT |
Bonne |
5x |
DISTINCT |
Mauvaise |
1/4x |
OVER |
Bonne |
2-5x |
OVER |
Mauvaise |
1/5x |
INNER JOIN |
Bonne |
10x |
INNER JOIN |
Mauvaise |
2x |
OUTER JOIN |
Bonne |
3x |
OUTER JOIN |
Mauvaise |
0,1x |
Pour plus d’informations, voir Actualisation incrémentielle par les opérateurs.
Optimisation des performances du mode d’actualisation incrémentielle pour les tables dynamiques complexes¶
Les tables dynamiques contiennent généralement plusieurs opérateurs, ce qui rend plus difficile la prévision de leurs performances avec des actualisations incrémentielles. Cette section explique comment relever ce défi et donne quelques conseils pour améliorer les performances des tables dynamiques complexes.
Lorsque plusieurs opérateurs sont impliqués, les actualisations incrémentielles calculent les modifications en travaillant sur chaque opérateur séparément, en le transformant en un fragment de plan de requête qui peut calculer les modifications en fonction de ses entrées. Pour chaque entrée, ce nouveau fragment peut demander l’entrée avant les changements, après les changements ou simplement les changements eux-mêmes. En appliquant ce processus à chaque opérateur de la requête d’origine, vous obtenez un nouveau plan de requête qui calcule les changements en utilisant une combinaison de balayages de changements et de balayages complets de tables. Ce plan est optimisé par l’optimiseur de requêtes de Snowflake et exécuté comme n’importe quelle autre requête.
Lorsqu’une actualisation incrémentielle ne donne pas de bonnes performances, c’est généralement parce qu’il y a trop de changements ou que la localité est mauvaise. Les requêtes complexes rendent plus difficile l’identification de ces problèmes. Les performances des opérateurs incrémentaux dépendent généralement de la quantité de changements et de la localité de leurs entrées. Toutefois, ces entrées sont les sorties d’autres opérateurs, de sorte que la quantité et la localisation des données peuvent changer au fur et à mesure qu’elles passent par les opérateurs.
Par conséquent, pour comprendre les performances d’une actualisation incrémentielle complexe, il faut prendre en compte les données de chaque opérateur séparément. Voici quelques scénarios courants et des suggestions pour y remédier :
Scénario |
Recommandation |
---|---|
Vous joignez des tables sur plusieurs colonnes, vous ne pouvez donc pas utiliser CLUSTER BY sur toutes ces colonnes simultanément. |
Privilégiez le clustering des grandes tables par clés qui changent fréquemment. Par exemple, dans un schéma en étoile avec une grande table de dimensions, concentrez-vous sur le clustering de la table de dimensions. Envisagez de créer plusieurs copies du même ensemble de données, chacune étant clusterisée par des clés différentes, et utilisez-les dans des contextes pertinents. |
Vous avez un GROUP BY ou un OVER sur de nombreuses jointures. |
Veillez à ce que les tables sources soient mises en cluster au moyen de clés de groupe/partitionnement et envisagez de répartir les jointures et l’agrégation dans deux tables dynamiques distinctes. Notez que les jointures externes interagissent mal avec les agrégations. |