SELECTSELECT

SELECT

Query tags Snowflake : un monitoring plus fin

By Ian WhitestoneFeb 7, 20237 min read

Cette page est également disponible en English, Deutsch, Español, Italiano, 日本語 et Português.

Les query tags Snowflake permettent d'associer des métadonnées arbitraires à chaque requête. Dans cet article, nous vous montrons comment les exploiter pour gagner en visibilité et mieux piloter les coûts et la performance de vos requêtes Snowflake.

Qu'est-ce qu'un query tag dans Snowflake ?

Les query tags sont un paramètre optionnel au niveau de la session qui permet d'associer une chaîne de caractères à n'importe quelle instruction SQL Snowflake. Ils peuvent contenir jusqu'à 2000 caractères, sans restriction de type. La valeur du query tag de chaque requête est accessible dans les vues query_history de Snowflake, ce qui ouvre la voie à de nombreux cas d'usage.

À noter : les query tags se distinguent des object tags. Tous deux servent à structurer le monitoring et à améliorer la visibilité au sein de votre compte Snowflake. En revanche, les object tags s'appliquent à des objets persistants du compte, comme les utilisateurs, les rôles, les tables, les vues, les fonctions, etc.

Pourquoi utiliser les query tags dans Snowflake ?

Pour la plupart des utilisateurs de Snowflake, les coûts de calcul des requêtes exécutées dans des virtual warehouses représentent l'essentiel de la dépense Snowflake. S'il est possible d'attribuer ces coûts à différents utilisateurs en calculant le coût par requête, cette granularité reste souvent insuffisante, car un seul compte applicatif en production peut concentrer la majorité des requêtes — et des coûts.

Les query tags permettent une attribution des coûts bien plus fine. Si une instruction SQL, ou une série d'instructions SQL, est associée à un modèle de données dans un pipeline, vous pouvez leur attribuer le même query tag. Les coûts se rattachent alors facilement à l'ensemble des requêtes portant ce tag. L'alternative consiste à regrouper par query_text, ce qui empêche d'agréger plusieurs instructions SQL liées entre elles. Cette approche tombe également à plat dès que le texte SQL d'un modèle de données évolue, ce qui finit toujours par arriver.

Les query tags servent aussi à un monitoring plus granulaire de la performance des requêtes. Pour reprendre l'exemple précédent, vous pouvez suivre le temps total d'exécution de chaque modèle de données en cumulant le temps écoulé sur l'ensemble des requêtes associées. De même, si un ensemble de requêtes alimente des dashboards applicatifs destinés aux utilisateurs finaux, les query tags rendent possible un monitoring de performance ciblé.

Enfin, les query tags permettent de relier les requêtes à des métadonnées issues d'autres systèmes. Un query tag peut par exemple contenir un dashboard_id, ce qui permet de cumuler les coûts d'un dashboard donné, puis d'en croiser la fréquence d'utilisation avec les métadonnées de l'outil de BI.

Comment utiliser les query tags dans Snowflake ?

Définir des tags par défaut

Les query tags sont un paramètre de session, mais des valeurs par défaut peuvent être fixées au niveau du compte ou de l'utilisateur. Par exemple :

1alter user shauna set query_tag = '{"team": "engineering", "user": "shauna"}';

Toutes les requêtes lancées par cet utilisateur porteront désormais ce tag par défaut.

Définir des query tags au niveau de la session

Utilisez la commande alter session pour définir le query tag. Une fois cette commande exécutée, toutes les requêtes lancées dans la même session seront taguées avec cette chaîne.

alter session set query_tag='users_model';

-- this query will be tagged with 'users_model'
create or replace table users_tmp as (
  select *
  from raw_users
  where
    not deleted
    and created_at > current_date - 1
);

-- this will also be tagged with 'users_model'
insert into users
from users_tmp
;

Déplier le code

Nous recommandons de privilégier autant que possible les valeurs par défaut au niveau utilisateur, afin d'éviter les appels fréquents à alter session, qui ajoutent de la latence à l'exécution globale des requêtes.

Définir des query tags en Python

Si vous utilisez Python pour exécuter vos requêtes, il existe deux façons de définir des query tags.

À la création de la connexion

Lors de la création de votre objet de connexion avec le connecteur Python Snowflake, vous pouvez définir des paramètres de session dès le départ. Dans l'exemple ci-dessous, toutes les requêtes exécutées via cet objet con seront taguées DATA_MODELLING_PIPELINE.

con = snowflake.connector.connect(
    user='XXXX',
    password='XXXX',
    account='XXXX',
    session_parameters={
        'QUERY_TAG': 'DATA_MODELLING_PIPELINE',
    }
)

Modification manuelle via alter session

Si vous ne souhaitez pas que toutes les requêtes de votre session portent le même tag, exécutez plutôt alter session set query_tag = 'XXX' juste avant de lancer vos requêtes.

con.cursor().execute("alter session set query_tag='users_model'")

query = """
create or replace table users_tmp as (
  select *
  from raw_users
  where
    not deleted
    and created_at > current_date - 1
)
"""

con.cursor().execute(query) # tagged with 'users_model'
con.cursor().execute("insert into users from users_tmp") # tagged with 'users_model'

Déplier le code

Définir des query tags dans dbt

Si vous utilisez dbt, trois options s'offrent à vous pour définir des query tags :

  1. Les définir une fois pour toutes dans votre profiles.yml ( source). Toutes les requêtes exécutées dans votre projet dbt porteront alors cette valeur.
  2. Définir des tags pour tous les modèles d'un resource_path donné, ou pour un seul modèle, en ajoutant un +query_tag dans votre dbt_project.yml. Pour les modèles individuels, vous pouvez aussi spécifier le query tag dans la configuration du modèle, par exemple {{ config(query_tag = 'XXX') }}. Si un query tag par défaut a été défini dans profiles.yml, il sera écrasé par ces définitions plus précises.
  3. Créer une macro set_query_tag qui attribue automatiquement le nom du modèle comme query tag pour tous les modèles de votre projet.

Consultez la documentation dbt pour des exemples de chacune de ces options, et prenez bien note du mode de défaillance signalé : les requêtes peuvent être taguées avec une valeur incorrecte en cas d'erreur survenant en amont.

Nous avons récemment publié un nouveau package dbt, dbt-snowflake-query-tags, qui tague toutes les requêtes émises par dbt avec un ensemble complet de métadonnées. N'hésitez pas à l'essayer.

Utiliser des chaînes JSON

Pour définir des query tags, nous recommandons un objet JSON, gage de simplicité et de cohérence. En reprenant l'exemple du tagging par modèle de données, un objet JSON permet d'ajouter des informations comme l'environnement d'exécution, la version, le déclencheur du modèle (exécution planifiée ou manuelle ?), et bien d'autres.

import json

query_tag = {
  'app_name': 'pipeline',
  'model_name': 'users',
  'environment': 'prod',
  'version': 'v1.2',
  'trigger': 'schedule'
}
con.cursor().execute(f"alter session set query_tag='{json.dumps(query_tag)}'")

con.cursor().execute(model_sql)

Exploiter les query tags pour le monitoring des coûts et de la performance Snowflake

Les query tags apparaissent dans les vues query history pour chaque query_id. Voici un exemple de requête qui affiche la performance moyenne par query_tag :

Si le query_tag contient un objet JSON, il peut être parsé et segmenté selon n'importe quelle clé. En reprenant l'exemple ci-dessus :

select
    query_tag,
    count(*) as num_executions,
    avg(total_elapsed_time/1000) as avg_total_elapsed_time_s
from snowflake.account_usage.query_history
where
    start_time > current_date - 7
group by 1

Utiliser le package dbt-snowflake-monitoring

Si vous utilisez le package dbt de SELECT pour le monitoring des coûts et de la performance, vous pouvez analyser les coûts par query tag, en plus de la performance :

select
    try_parse_json(query_tag)['model_name']::string as model_name,
    count(*) as num_executions,
    avg(total_elapsed_time/1000) as avg_total_elapsed_time_s
from snowflake.account_usage.query_history
where
    try_parse_json(query_tag)['app_name']::string = 'pipeline'
    and start_time > current_date - 7
group by 1

Vous constaterez aussi que ces requêtes s'exécutent bien plus vite que celles lancées sur les vues account usage de Snowflake, car la table est matérialisée et triée par start_time pour atteindre un clustering optimal.

Utiliser des commentaires de requête plutôt que des query tags

Autre pratique courante pour taguer les requêtes : ajouter un commentaire à la fin 1 de chaque requête :

select
    try_parse_json(query_tag)['model_name']::string as model_name,
    count(*) as num_executions,
    sum(query_cost) as total_cost,
    avg(total_elapsed_time_s) as avg_total_elapsed_time_s
from query_history_enriched
where
    try_parse_json(query_tag)['app_name']::string = 'pipeline'
    and start_time > current_date - 7
group by 1

Cette approche présente l'avantage d'être universellement applicable à tous les data warehouses et plus simple à mettre en œuvre, puisqu'elle ne nécessite pas d'exécuter d'instruction alter session. Autre atout : la performance, car exécuter une instruction alter session implique un aller-retour réseau vers Snowflake 2. C'est acceptable dans la plupart des cas, mais cela peut poser problème pour les applications où 100 à 200 ms supplémentaires de temps de réponse comptent. Enfin, comme le texte d'une requête peut atteindre 1 Mo, les commentaires de requête peuvent contenir bien plus de métadonnées que les query tags, limités à 2000 caractères.

Lorsque c'est possible, nous recommandons les query tags, car ils sont bien plus simples à parser et à analyser en aval. Si les métadonnées de vos requêtes risquent de dépasser 2000 caractères, optez pour les commentaires de requête.

Notes

  1. Snowflake supprime automatiquement les commentaires placés en début de requête : il faut donc les ajouter à la fin.

  2. L'instruction alter session est en elle-même extrêmement rapide, environ 30 ms en moyenne.

Ian Whitestone·Co-fondateur et CEO de SELECT

Ian est co-fondateur et CEO de SELECT, une plateforme SaaS de gestion et d'optimisation des coûts Snowflake. Avant de lancer SELECT, Ian a passé 6 ans à diriger des équipes data science et engineering full stack chez Shopify et Capital One. Chez Shopify, il a piloté l'optimisation du data warehouse et le renforcement de l'observabilité des coûts.