Le query tag di Snowflake permettono di associare metadati arbitrari a ogni query. In questo articolo vediamo come usarle per ottenere maggiore visibilità e monitorare con precisione costi e performance delle query Snowflake.
Che cos'è una query tag in Snowflake?
Le query tag sono un parametro opzionale a livello di sessione che consente di etichettare qualsiasi istruzione SQL di Snowflake con una stringa. Possono raggiungere i 2000 caratteri e contenere qualunque carattere. I valori delle query tag per ogni query sono disponibili nell'output delle viste query_history di Snowflake, il che li rende sfruttabili in una vasta gamma di casi d'uso.
Va sottolineato che le query tag sono cosa diversa dagli object tag. Entrambi servono allo scopo comune di rendere il monitoraggio più strutturato e di migliorare la visibilità all'interno del proprio account Snowflake. Tuttavia, gli object tag si applicano a oggetti persistenti dell'account come utenti, ruoli, tabelle, viste, funzioni e altro ancora.
Perché usare le query tag in Snowflake?
Per la maggior parte degli utenti Snowflake, i costi di compute generati dalle query eseguite sui virtual warehouse rappresentano la parte preponderante della spesa Snowflake. Sebbene sia possibile attribuire la spesa di compute di un warehouse ai diversi utenti calcolando il costo per query, spesso questo livello di granularità non basta, dato che un singolo account utente di produzione può generare la stragrande maggioranza di query e di costi.
Le query tag consentono un'attribuzione dei costi molto più granulare. Se si ha una singola istruzione SQL, o una serie di istruzioni SQL associate a un data model di una pipeline, è possibile assegnare loro la stessa query tag. I costi possono poi essere attribuiti facilmente a tutte le query collegate a quella tag. L'alternativa consisterebbe nel raggruppare per query_text, approccio che però non permette di accorpare più istruzioni SQL correlate e che si sgretola appena il testo SQL di un data model viene inevitabilmente modificato.
Le query tag sono utili anche per un monitoraggio più granulare delle performance delle query. Riprendendo l'esempio precedente, si potrebbe voler monitorare il tempo di esecuzione totale di ciascun data model sommando il tempo trascorso di tutte le query associate. In alternativa, se un insieme di query alimenta dashboard di applicazioni rivolte agli utenti finali, le query tag permettono un monitoraggio delle performance molto più mirato.
Infine, le query tag consentono di collegare le query a metadati provenienti da altri sistemi. Una query tag potrebbe contenere un dashboard_id, permettendo di aggregare tutti i costi relativi a una singola dashboard e poi verificare, tramite i metadati dello strumento di BI, con quale frequenza quella dashboard viene utilizzata.
Come si usano le query tag in Snowflake?
Impostare tag predefiniti
Le query tag sono un parametro a livello di sessione, ma è possibile definire valori predefiniti a livello di account e di utente. Ad esempio:
1alter user shauna set query_tag = '{"team": "engineering", "user": "shauna"}';
Da quel momento, ogni query eseguita da questo utente avrà questa tag predefinita.
Impostare le query tag a livello di sessione
Utilizzare il comando alter session per impostare la query tag. Dopo l'esecuzione di questo comando, tutte le query successive eseguite nella stessa sessione verranno etichettate con quella stringa.
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
;
Espandi codice
Consigliamo di sfruttare i valori predefiniti per utente quando possibile, così da evitare frequenti chiamate alter session che aggiungono latenza all'esecuzione complessiva delle query.
Impostare le query tag in Python
Se si utilizza Python per eseguire le query, ci sono due modi per impostare le query tag.
Impostazione una tantum alla creazione della connessione
Quando si crea l'oggetto connection con lo Snowflake Python Connector, è possibile definire in anticipo qualsiasi parametro di sessione. Nell'esempio seguente, tutte le query eseguite a partire dall'oggetto con saranno etichettate con DATA_MODELLING_PIPELINE.
con = snowflake.connector.connect(
user='XXXX',
password='XXXX',
account='XXXX',
session_parameters={
'QUERY_TAG': 'DATA_MODELLING_PIPELINE',
}
)
Modifica manuale tramite alter session
Se non si vuole che tutte le query della sessione abbiano la stessa tag, si può eseguire alter session set query_tag = 'XXX' prima delle query effettive.
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'
Espandi codice
Impostare le query tag in dbt
Se si utilizza dbt, ci sono tre opzioni per impostare le query tag:
- Si possono impostare una sola volta nel file
profiles.yml( fonte). Tutte le query del progetto dbt verranno etichettate con quel valore. - Le tag possono essere impostate per tutti i model sotto un determinato
resource_path, oppure per un singolo model, aggiungendo+query_tagnel filedbt_project.yml. Per i singoli model è anche possibile specificare la query tag nella config del model, ad esempio{{ config(query_tag = 'XXX') }}. Se è stata definita una query tag predefinita inprofiles.yml, verrà sovrascritta da queste tag più specifiche. - È possibile creare una macro
set_query_tagche imposta automaticamente la query tag sul nome del model per tutti i model del progetto.
Si rimanda alla documentazione di dbt per gli esempi di ciascuna di queste opzioni, prestando attenzione alla possibile modalità di errore segnalata: in caso di problemi specifici a monte, le query possono finire con una tag errata.
Abbiamo da poco rilasciato un nuovo pacchetto dbt, dbt-snowflake-query-tags, che etichetta tutte le query generate da dbt con un set completo di metadati: dategli un'occhiata.
Utilizzare stringhe JSON
Per impostare le query tag, consigliamo di usare un oggetto JSON, sia per praticità sia per coerenza. Riprendendo l'esempio del tagging dei data model, con un oggetto JSON si possono aggiungere informazioni come l'ambiente in cui è stato eseguito il model, la versione, il trigger di esecuzione (esecuzione pianificata o invocata manualmente?) e altro ancora.
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)
Come usare le query tag per monitorare costi e performance in Snowflake
Le query tag sono esposte nelle viste query history per ogni query_id. Ecco una query di esempio che mostra le performance medie raggruppate per query_tag:
Se la query_tag contiene un oggetto JSON, può essere parsata e segmentata in base a una qualsiasi delle chiavi. Riprendendo l'esempio precedente:
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
Utilizzare il pacchetto dbt-snowflake-monitoring
Se si utilizza il pacchetto dbt di SELECT per il monitoraggio di costi e performance, oltre alle performance è possibile analizzare anche il costo per query tag:
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
Noterete inoltre che queste query vengono eseguite molto più velocemente di una query sulle viste account usage di Snowflake, perché la tabella è materializzata e ordinata per start_time in modo da ottenere uno stato di clustering ottimale.
Usare i query comment al posto delle query tag
Un'altra pratica diffusa per il tagging delle query consiste nell'aggiungere un commento in fondo 1 a ciascuna query:
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
Questo approccio ha il vantaggio di essere applicabile in modo universale a tutti i data warehouse ed è più semplice da implementare, perché non richiede l'esecuzione di un'istruzione alter session. Un altro vantaggio interessante è sul fronte delle performance: l'esecuzione di un alter session comporta una chiamata di rete di andata e ritorno verso Snowflake
2. Nella maggior parte dei casi d'uso non è un problema, ma può non essere accettabile in applicazioni in cui 100-200 ms di latenza in più sul tempo di risposta fanno la differenza. Infine, poiché il testo della query può arrivare fino a 1 MB, i query comment possono contenere molti più metadati rispetto alle query tag, che sono limitate a 2000 caratteri.
Ove possibile, consigliamo di utilizzare le query tag, perché sono molto più semplici da parsare e analizzare a valle. Se è prevedibile che i metadati delle query superino i 2000 caratteri, meglio puntare sui query comment.
Note
Snowflake rimuove automaticamente tutti i commenti all'inizio di ogni query, quindi è necessario aggiungerli in fondo.
L'istruzione
alter sessionin sé è estremamente veloce: in media circa 30 ms.
Ian Whitestone·Co-founder & CEO di SELECT
Ian è Co-founder e CEO di SELECT, una piattaforma SaaS per la gestione e l'ottimizzazione dei costi di Snowflake. Prima di fondare SELECT, ha trascorso 6 anni alla guida di team full stack di data science ed engineering in Shopify e Capital One. In Shopify ha guidato le attività di ottimizzazione del data warehouse e il miglioramento dell'osservabilità dei costi.