Mit Snowflake Query Tags können Sie beliebige Metadaten an jede Abfrage hängen. In diesem Beitrag zeigen wir, wie Sie damit Kosten und Performance Ihrer Snowflake-Abfragen transparenter machen und gezielter überwachen.
Was ist ein Query Tag in Snowflake?
Query Tags sind ein optionaler Parameter auf Session-Ebene, mit dem sich jede Snowflake-SQL-Anweisung mit einem String versehen lässt. Sie können bis zu 2000 Zeichen lang sein und beliebige Zeichen enthalten. Die Query-Tag-Werte einer Abfrage finden Sie in der Ausgabe der query_history-Views in Snowflake und lassen sich so für die unterschiedlichsten Anwendungsfälle nutzen.
Wichtig zu wissen: Query Tags sind nicht dasselbe wie Object Tags. Beide sollen zwar strukturiertes Monitoring ermöglichen und die Transparenz in Ihrem Snowflake-Account erhöhen. Object Tags kommen jedoch bei persistenten Account-Objekten wie Users, Roles, Tables, Views, Functions und Ähnlichem zum Einsatz.
Warum sollten Sie Query Tags in Snowflake einsetzen?
Bei den meisten Snowflake-Nutzern entfällt der Löwenanteil der Snowflake-Ausgaben auf die Compute-Kosten von Abfragen in Virtual Warehouses. Zwar lassen sich Compute-Kosten innerhalb eines Warehouse über die Kostenberechnung pro Query einzelnen Usern zuordnen, doch ist das oft nicht granular genug: Ein einziger produktiver User-Account kann den Großteil der Abfragen – und damit der Kosten – verursachen.
Query Tags ermöglichen eine deutlich feinere Kostenzuordnung. Wenn Sie eine einzelne SQL-Anweisung oder eine Reihe von SQL-Anweisungen haben, die zu einem Datenmodell in einer Pipeline gehören, können Sie ihnen denselben Query Tag zuweisen. Die Kosten aller Abfragen mit diesem Tag lassen sich anschließend mühelos aggregieren. Die Alternative wäre eine Gruppierung nach query_text – damit lassen sich aber mehrere zusammengehörige SQL-Anweisungen nicht gemeinsam erfassen. Außerdem funktioniert dieser Ansatz nicht mehr, sobald sich der SQL-Text eines Datenmodells – wie es früher oder später passiert – ändert.
Auch für granulareres Query-Performance-Monitoring eignen sich Query Tags. Um beim vorherigen Beispiel zu bleiben: Sie können die Gesamtlaufzeit jedes Datenmodells überwachen, indem Sie die Elapsed Time aller zugehörigen Abfragen aufsummieren. Werden bestimmte Abfragen für nutzerseitige Anwendungs-Dashboards verwendet, lässt sich mit Query Tags ein gezielteres Performance-Monitoring umsetzen.
Nicht zuletzt erlauben Query Tags, Abfragen mit Metadaten aus anderen Systemen zu verknüpfen. Ein Query Tag kann beispielsweise eine dashboard_id enthalten – so lassen sich alle Kosten für ein einzelnes Dashboard aggregieren und über die Metadaten des BI-Tools auswerten, wie häufig dieses Dashboard tatsächlich genutzt wird.
Wie nutzen Sie Query Tags in Snowflake?
Standard-Tags festlegen
Query Tags sind zwar ein Parameter auf Session-Ebene, Standardwerte lassen sich aber auf Account- und User-Ebene festlegen. Zum Beispiel:
1alter user shauna set query_tag = '{"team": "engineering", "user": "shauna"}';
Jede Abfrage dieses Users erhält ab sofort automatisch diesen Standard-Tag.
Query Tags auf Session-Ebene setzen
Verwenden Sie den Befehl alter session, um den Query Tag zu setzen. Danach werden alle weiteren Abfragen in derselben Session mit diesem String getaggt.
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
;
Code aufklappen
Wir empfehlen, wann immer möglich User-Defaults zu nutzen, um häufige alter session-Aufrufe zu vermeiden – diese verlängern die Gesamtausführungszeit der Abfragen.
Query Tags in Python setzen
Wenn Sie Abfragen mit Python ausführen, gibt es zwei Wege, Query Tags zu setzen.
Einmalig beim Aufbau der Connection
Beim Erstellen des Connection-Objekts mit dem Snowflake Python Connector können Sie Session-Parameter gleich initial mitgeben. Im folgenden Beispiel werden alle Abfragen, die über dieses con-Objekt laufen, mit DATA_MODELLING_PIPELINE getaggt.
con = snowflake.connector.connect(
user='XXXX',
password='XXXX',
account='XXXX',
session_parameters={
'QUERY_TAG': 'DATA_MODELLING_PIPELINE',
}
)
Manuelle Anpassung per alter session
Wenn nicht alle Abfragen Ihrer Session denselben Tag tragen sollen, können Sie stattdessen vor Ihren eigentlichen Abfragen ein alter session set query_tag = 'XXX' ausführen.
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'
Code aufklappen
Query Tags in dbt setzen
Wer dbt einsetzt, hat drei Möglichkeiten, Query Tags zu setzen:
- Einmalig in Ihrer
profiles.yml(Quelle). Alle Abfragen Ihres dbt-Projekts werden dann mit diesem Wert getaggt. - Tags lassen sich für alle Modelle unter einem bestimmten
resource_pathoder für ein einzelnes Modell setzen, indem Sie+query_tagin Ihrerdbt_project.ymlergänzen. Für einzelne Modelle können Sie den Query Tag auch direkt in der Model-Config angeben, also{{ config(query_tag = 'XXX') }}. Ein Standard-Query-Tag aus derprofiles.ymlwird durch jeden dieser spezifischeren Tags überschrieben. - Sie können ein Macro
set_query_taganlegen, das den Query Tag für alle Modelle Ihres Projekts automatisch auf den Modellnamen setzt.
Beispiele zu allen drei Optionen finden Sie in der dbt-Dokumentation. Beachten Sie außerdem den dort beschriebenen möglichen Fehlerfall, bei dem Abfragen einen falschen Tag erhalten, wenn upstream bestimmte Fehler auftreten.
Vor Kurzem haben wir zudem ein neues dbt-Package veröffentlicht – dbt-snowflake-query-tags –, das alle von dbt ausgeführten Abfragen mit umfassenden Metadaten taggt. Schauen Sie es sich an.
JSON-Strings verwenden
Beim Setzen von Query Tags empfehlen wir ein JSON-Objekt – das erleichtert die Handhabung und sorgt für Konsistenz. Bleiben wir beim Beispiel des Datenmodell-Taggings: Mit einem JSON-Objekt können wir zusätzliche Informationen ergänzen, etwa die Umgebung, in der das Modell ausgeführt wurde, die Version, den Auslöser für die Ausführung (geplanter Lauf oder manueller Aufruf?) und vieles mehr.
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)
Query Tags für Kosten- und Performance-Monitoring in Snowflake nutzen
Query Tags werden in den Query-History-Views zu jeder query_id ausgewiesen. Hier ein Beispiel für eine Abfrage, die die durchschnittliche Query-Performance nach query_tag auswertet:
Enthält der query_tag ein JSON-Objekt, lässt es sich parsen und nach jedem beliebigen Schlüssel segmentieren. Anhand des obigen Beispiels:
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
Das Package dbt-snowflake-monitoring einsetzen
Wenn Sie das dbt-Package von SELECT für Kosten- und Performance-Monitoring verwenden, können Sie zusätzlich zur Performance auch die Kosten nach Query Tag auswerten:
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
Sie werden außerdem feststellen, dass diese Abfragen deutlich schneller laufen als eine Abfrage gegen die Account-Usage-Views von Snowflake – denn die Tabelle ist materialisiert und nach start_time sortiert, was zu einem gut geclusterten Zustand führt.
Query Comments statt Query Tags
Eine weitere gängige Methode zum Taggen von Abfragen ist es, am Ende 1 jeder Abfrage einen Kommentar anzuhängen:
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
Der Vorteil: Dieser Ansatz funktioniert universell mit allen Data Warehouses und ist einfacher umzusetzen, da kein alter session-Statement nötig ist. Ein weiterer Pluspunkt ist die Performance: Ein alter session-Statement bedeutet einen Roundtrip-Netzwerkaufruf zu Snowflake
2. Für die meisten Anwendungsfälle ist das unkritisch, kann aber in Applikationen ins Gewicht fallen, in denen 100–200 ms zusätzliche Antwortzeit eine Rolle spielen. Hinzu kommt: Da der Query-Text bis zu 1 MB groß sein darf, können Query Comments deutlich mehr Metadaten aufnehmen als Query Tags, die auf 2000 Zeichen begrenzt sind.
Wo möglich, empfehlen wir Query Tags, da sie sich downstream wesentlich einfacher parsen und auswerten lassen. Können Ihre Query-Metadaten 2000 Zeichen überschreiten, bleiben Sie besser bei Query Comments.
Anmerkungen
Snowflake entfernt automatisch alle Kommentare am Anfang einer Abfrage – Sie müssen sie daher ans Ende der Abfrage anhängen.
Das
alter session-Statement selbst läuft extrem schnell und benötigt im Schnitt rund 30 ms.
Ian Whitestone · Co-Founder & CEO von SELECT
Ian ist Co-Founder und CEO von SELECT, einer SaaS-Plattform für Snowflake-Kostenmanagement und -Optimierung. Vor SELECT leitete er sechs Jahre lang Full-Stack-Teams aus Data Science und Engineering bei Shopify und Capital One. Bei Shopify verantwortete er die Optimierung des Data Warehouse und den Ausbau der Kostentransparenz.