Optimiser les requêtes pour l’actualisation incrémentielle

Utilisez cette page lorsque vous concevez une nouvelle requête de table dynamique ou que vous souhaitez optimiser une requête existante pour une actualisation incrémentielle. Ce guide montre quels opérateurs fonctionnent bien, qui nécessitent un traitement prudent, et comment restructurer les requêtes pour améliorer les performances.

Pour une liste complète des constructions de requête prises en charge pour l’actualisation incrémentielle, voir Requêtes prises en charge pour les tables dynamiques.

Attentes en matière de performances par opérateur

Avant d’optimiser une requête de table dynamique, comprenez quels opérateurs bénéficient de l’actualisation incrémentielle et lesquels peuvent causer des problèmes.

Note

Les requêtes courtes (moins de 10 secondes) peuvent présenter des gains de performances plus faibles en raison de frais généraux fixes tels que l’optimisation des requêtes et la planification des entrepôts.

Opérateurs qui fonctionnent toujours bien

Ces opérateurs fonctionnent efficacement avec une actualisation incrémentielle :

  • SELECT

  • WHERE

  • FROM <base table>

  • UNION ALL

  • QUALIFY [ RANK | ROW_NUMBER | DENSE_RANK ] … = 1

Pour plus de détails sur la façon dont Snowflake traite chaque opérateur, voir la table de référence des opérateurs.

Opérateurs concernés par la localité des données

Pour ces opérateurs, la performance dépend de la localité des données, qui correspond à la manière d’organiser vos données et à l’endroit où les changements se produisent par rapport à vos clés :

  • INNER JOIN

  • OUTER JOIN

  • GROUP BY

  • DISTINCT

  • OVER (fonctions de fenêtre)

Lorsque les modifications n’affectent qu’une petite partie des clés de regroupement ou de partition, ces opérateurs fonctionnent bien. Une faible localité des données ou des modifications réparties sur de nombreuses clés peuvent rendre l’actualisation incrémentielle plus lente par rapport à l’actualisation complète.

Pour plus de détails sur la façon dont Snowflake traite chaque opérateur, voir la table de référence des opérateurs.

Modèles d’optimisation courants

Les sections suivantes présentent des modèles communs pour optimiser les requêtes qui utilisent des opérateurs sensibles à la localité.

Optimiser les agrégations

Lorsque vous utilisez GROUP BY, Snowflake recalcule les agrégats pour chaque clé de regroupement contenant des modifications. Les performances dépendent des facteurs suivants :

  • Clustering de données : Les données sources regroupées par clés de regroupement sont les plus performantes.

  • Modifier la distribution : Visez des changements qui affectent moins de 5 % des clés de regroupement.

  • Complexité des clés : Les références de colonnes simples sont plus performantes que les expressions composées.

Problème : expressions composées dans les clés de regroupement

Cette requête fonctionne mal car la clé de regroupement est une expression :

CREATE DYNAMIC TABLE hourly_sums
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT DATE_TRUNC('minute', ts), SUM(amount)
  FROM transactions
  GROUP BY 1;
Copy

Solution : matérialiser l’expression

Fractionner en deux tables dynamiques pour exposer une clé de regroupement simple :

CREATE DYNAMIC TABLE transactions_with_minute
  TARGET_LAG = DOWNSTREAM
  WAREHOUSE = my_warehouse
AS
  SELECT DATE_TRUNC('minute', ts) AS ts_minute, amount
  FROM transactions;

CREATE DYNAMIC TABLE hourly_sums
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT ts_minute, SUM(amount)
  FROM transactions_with_minute
  GROUP BY 1;
Copy

Maintenant GROUP BY fonctionne sur une colonne simple, et la table intermédiaire bénéficie d’une meilleure localité des données.

Optimiser les jointures

La performance de la jointure dépend des changements de côté et de la manière de regrouper les données.

INNER JOIN : Snowflake joint les modifications du côté gauche à la table de droite, puis joint les modifications du côté droit à la table de gauche. Les jointures fonctionnent bien lorsqu’un côté est petit ou change peu souvent.

OUTER JOIN : Snowflake doit aussi calculer les valeurs NULL pour les lignes ne correspondant pas. Les changements de côté affectent considérablement la performance.

Problème : grande table des deux côtés avec un clustering faible

Aucune des tables sources n’est clusterisée par la clé de jointure :

CREATE DYNAMIC TABLE order_details
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT o.order_id, o.customer_id, p.product_name, o.quantity
  FROM orders o
  JOIN products p ON o.product_id = p.product_id;
Copy

Solution : clusterisez la table qui change moins souvent

Clusterisez la table de dimensions par la clé de jointure. Ensuite, la jointure bénéficie d’une meilleure localité :

ALTER TABLE products CLUSTER BY (product_id);

CREATE DYNAMIC TABLE order_details
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT o.order_id, o.customer_id, p.product_name, o.quantity
  FROM orders o
  JOIN products p ON o.product_id = p.product_id;
Copy

Pour OUTER JOINs :

  • Placez la table qui change le plus souvent sur le côté LEFT.

  • Essayez de réduire les changements sur le côté opposé au mot-clé OUTER.

  • Pour FULL OUTER JOINs, une bonne localité est essentielle des deux côtés.

Optimiser les fonctions de fenêtre

Snowflake recalcule les fonctions de fenêtre pour chaque clé de partition contenant des modifications. Optimisez-les de la même manière que GROUP BY.

Exigences relatives aux clés :

  • Toujours inclure une clause PARTITION BY. Les fonctions de fenêtre sans PARTITION BY donne lieu à un recalcul complet.

  • Regrouper les données sources par clés de partition.

  • Maintenez les modifications à moins de 5 % des partitions.

Problème : fonction de fenêtre sans clustering de partition

La table source n’est pas clusterisée par la clé de partition :

CREATE DYNAMIC TABLE ranked_sales
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT
    region,
    salesperson,
    amount,
    RANK() OVER (PARTITION BY region ORDER BY amount DESC) as sales_rank
  FROM daily_sales;
Copy

Solution : clusterisez par la clé de partition

Clusterisez la table source en fonction de la clé de partition afin que la fonction de fenêtre bénéficie de la localité :

ALTER TABLE daily_sales CLUSTER BY (region);

CREATE DYNAMIC TABLE ranked_sales
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT
    region,
    salesperson,
    amount,
    RANK() OVER (PARTITION BY region ORDER BY amount DESC) as sales_rank
  FROM daily_sales;
Copy

Supprimer efficacement les doublons (DISTINCT et QUALIFY)

DISTINCT et QUALIFY peuvent supprimer les doublons, mais ils fonctionnent différemment.

DISTINCT : Est équivalent à GROUP BY ALL. La localité affecte directement les performances ; une faible localité entraîne des actualisations lentes.

QUALIFY avec ROW_NUMBER = 1 : Snowflake optimise le modèle QUALIFY ROW_NUMBER() ... = 1 lorsqu’il se trouve dans la projection de niveau supérieur de la table dynamique. Ce modèle fonctionne systématiquement plus rapidement qu’une actualisation complète.

L’optimisation fonctionne mieux lorsque toutes les clés PARTITION BY et ORDER BY dans la clause OVER() sont conservées dans la table dynamique (incluse dans la projection de niveau supérieur).

Recommandation : utiliser QUALIFY au lieu de DISTINCT lorsque cela est possible

L’exemple suivant utilise DISTINCT :

CREATE DYNAMIC TABLE unique_customers
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT DISTINCT customer_id, customer_name, email
  FROM customer_events;
Copy

L’exemple suivant utilise QUALIFY :

CREATE DYNAMIC TABLE unique_customers
  TARGET_LAG = '1 hour'
  WAREHOUSE = my_warehouse
AS
  SELECT customer_id, customer_name, email, event_time
  FROM customer_events
  QUALIFY ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY event_time DESC) = 1;
Copy

La version QUALIFY est plus explicite sur le doublon à conserver (le plus récent) et fonctionne toujours bien.

Supprimer les opérations DISTINCT redondantes

Chaque opération DISTINCT consomme des ressources à chaque actualisation. Lorsque vos données sont déjà uniques ou que vous éliminez les doublons en amont, supprimez les clauses DISTINCT inutiles.

Référence des opérateurs

Le tableau suivant explique comment Snowflake traite chaque opérateur SQL lors de l’actualisation incrémentielle :

Opérateur

Comment Snowflake les traite-t-elles ?

Notes sur les performances

SELECT

Applique les expressions aux lignes modifiées uniquement.

Bonnes performances. Aucune considération particulière.

WHERE

Évalue le prédicat sur les lignes modifiées uniquement.

Bonnes performances. Le coût augmente de façon linéaire avec les changements. Remarque : Un opérateur WHERE très sélectif peut nécessiter que l’entrepôt de données reste actif, même lorsque le résultat ne change pas.

FROM <table>

Analyse les micro-partitions que Snowflake a ajoutées ou supprimées depuis la dernière actualisation.

Le coût augmente avec le volume des partitions modifiées. Limitez les changements à environ cinq pour cent de la table source.

UNION ALL

Prend l’union des changements de chaque côté.

Bonnes performances. Aucune considération particulière.

WITH (CTEs)

Calcule les changements pour chaque expression de table commune.

Bonnes performances, mais évitez les définitions de table unique trop complexes. Envisagez de procéder à un fractionnement entre plusieurs tables dynamiques.

Agrégats scalaires

Recalcule entièrement l’agrégat lorsque l’entrée change.

À éviter dans les tables à performances critiques. Considérez plutôt le regroupement par une constante.

GROUP BY

Recalcule les agrégats pour les clés de regroupement modifiées.

Clusterisez la source en regroupant des clés. Évitez les expressions composées dans les clés. Voir Optimiser les agrégations.

DISTINCT

Est équivalent à GROUP BY ALL.

Sensible à la localité. Pensez à utiliser QUALIFY à la place. Voir Supprimer efficacement les doublons (DISTINCT et QUALIFY).

Fonctions de fenêtre

Recalcule pour les clés de partition modifiées.

Toujours inclure PARTITION BY. Clusterisez la source par clés de partition. Voir Optimiser les fonctions de fenêtre.

INNER JOIN

Les jointures changent de chaque côté avec l’autre table.

Bonnes performances lorsqu’un côté est petit. Clusterisez le côté qui change le moins fréquemment. Voir Optimiser les jointures.

OUTER JOIN

Combine la jonction intérieure avec des requêtes NOT EXISTS pour le calcul NULL.

Opérateur le plus sensible à la localité. Voir Optimiser les jointures.

LATERAL FLATTEN

Appliquez l’aplatissement uniquement aux lignes modifiées.

Bonnes performances. Le coût augmente de façon linéaire avec les changements.

QUALIFY avec classement

Utilise un chemin optimisé pour ROW_NUMBER/RANK/DENSE_RANK … = 1.

Hautement efficace. Placez QUALIFY au niveau de la projection de niveau supérieur de la table dynamique.