Optimieren von Abfragen für inkrementelle Aktualisierungen¶
Verwenden Sie diese Seite, wenn Sie eine neue Abfrage für eine dynamische Tabelle entwerfen oder eine bestehende Abfrage für eine inkrementelle Aktualisierung optimieren möchten. Dieses Leitfaden zeigt, welche Operatoren eine gute Leistung erbringen, welche eine sorgfältige Handhabung erfordern und wie Abfragen umstrukturiert werden können, um die Leistung zu verbessern.
Eine vollständige Liste der Abfragekonstrukte, die für die inkrementelle Aktualisierung unterstützt werden, finden Sie unter Unterstützte Abfragen für dynamische Tabellen.
Leistungserwartungen nach Operator¶
Bevor Sie eine Abfrage für eine dynamische Tabelle optimieren, sollten Sie verstehen, welche Operatoren von einer inkrementellen Aktualisierung profitieren und welche Probleme verursachen können.
Bemerkung
Bei kurzen Abfragen (weniger als 10 Sekunden) können aufgrund von festen Overheads wie Abfrageoptimierung und Warehouse-Planung die Leistungssteigerungen geringer ausfallen.
Operatoren, die gleichbleibend gute Leistung bieten¶
Diese Operatoren arbeiten effizient mit der inkrementellen Aktualisierung:
SELECTWHEREFROM-<base table>UNION ALLQUALIFY[RANK|ROW_NUMBER|DENSE_RANK] … = 1
Weitere Informationen dazu, wie Snowflake die einzelnen Operatoren verarbeitet, finden Sie in der -Operatoren-Referenztabelle.
Von Datenlokalität betroffene Operatoren¶
Für diese Operatoren hängt die Leistung von der Datenlokalität ab, also davon, wie Sie Ihre Daten organisieren und wo Änderungen in Bezug auf Ihre Schlüsseln auftreten:
INNER JOINOUTER JOINGROUP BYDISTINCTOVER(Fensterfunktionen)
Wenn Änderungen nur einen kleinen Teil der Gruppierungs- oder Partitionsschlüssel betreffen, funktionieren diese Operatoren gut. Eine schlechte Datenlokalität oder Änderungen, die auf viele Schlüssel verteilt sind, können dazu führen, dass die inkrementelle Aktualisierung langsamer ist als die vollständige Aktualisierung.
Weitere Informationen dazu, wie Snowflake die einzelnen Operatoren verarbeitet, finden Sie in der -Operatoren-Referenztabelle.
Gängige Optimierungsmuster¶
In den folgenden Abschnitten werden gängige Muster zur Optimierung von Abfragen gezeigt, die lokalitätsabhängige Operatoren verwenden.
Optimieren von Aggregationen¶
Wenn Sie GROUP BY verwenden, berechnet Snowflake die Aggregate für jeden Gruppierungsschlüssel neu, der Änderungen enthält. Die Verarbeitungsleistung hängt von folgenden Faktoren ab:
Daten-Clustering: Nach Gruppierungsschlüsseln geclusterte Quelldaten schneiden am besten ab.
Änderungsverteilung: Ziel sind Änderungen, die weniger als fünf Prozent der Gruppierungsschlüssel betreffen.
Schlüsselkomplexität: Einfache Spaltenreferenzen sind leistungsfähiger als zusammengesetzte Ausdrücke.
Problem: Zusammengesetzte Ausdrücke in Gruppierungsschlüsseln¶
Diese Abfrage ist schlecht, da der Gruppierungsschlüssel ein Ausdruck ist:
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;
Lösung: Materialisieren des Ausdrucks¶
Aufteilen in zwei dynamische Tabellen, um einen einfachen Gruppierungsschlüssel verfügbar zu machen:
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;
Jetzt wird GROUP BY auf eine einfache Spalte angewendet und die Zwischentabelle profitiert von besseren Datenlokalität.
Optimieren von Verknüpfungen¶
Die Verknüpfungsleistung hängt davon ab, welche Seite sich ändert und wie Sie die Daten clustern.
INNER JOIN: Snowflake verknüpft dann Änderungen von der linken Seite mit der rechten Tabelle und dann Änderungen von der rechten Seite mit der linken Tabelle. Verknüpfungen funktionieren gut, wenn eine Seite klein ist oder sich nur selten ändert.
OUTER JOIN: Snowflake muss auch NULL-Werte für nicht übereinstimmende Zeilen berechnen. Welche Seite sich ändert, wirkt sich erheblich auf die Leistung aus.
Problem: Große Tabelle auf beiden Seiten mit schlechtem Clustering¶
Keine der beiden Quelltabellen wird nach dem Verknüpfungsschlüssel geclustert:
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;
Lösung: Clustern der Tabelle, die sich weniger häufig ändert¶
Clustern Sie die Dimensionstabelle nach dem Verknüpfungsschlüssel. Dann profitiert die Verknüpfung von einer besseren Lokalität:
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;
Für OUTER JOINs:
Positionieren Sie die Tabelle, die sich häufiger ändert, auf die LEFT Seite.
Minimieren Sie die Änderungen auf der Seite, die dem Schlüsselwort OUTER gegenüberliegt.
Für FULL OUTER JOINs ist eine gute Lokalität auf beiden Seiten entscheidend.
Optimieren der Fensterfunktionen¶
Snowflake führt die Neuberechnungen für Fensterfunktionen für jeden Partitionsschlüssel durch, der Änderungen enthält. Optimieren Sie sie ähnlich wie GROUP BY.
Wichtigste Anforderungen:
Fügen Sie immer eine PARTITION BY-Klausel hinzu. Fensterfunktionen ohne PARTITION BY führen zu einer vollständigen Neuberechnung.
Clustern Sie die Quelldaten nach Partitionsschlüsseln.
Begrenzen Sie Änderungen auf weniger als fünf Prozent der Partitionen.
Problem: Fensterfunktion ohne Partitions-Clustering¶
Die Quelltabelle wird nicht nach dem Partitionsschlüssel geclustert:
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;
Lösung: Clustern nach dem Partitionsschlüssel¶
Clustern Sie die Quelltabelle nach dem Partitionsschlüssel, sodass die Fensterfunktion von der Lokalität profitiert:
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;
Effizientes Entfernen von Duplikaten (DISTINCT vs. QUALIFY)¶
Sowohl DISTINCT als auch QUALIFY können Duplikate entfernen, aber sie funktionieren anders.
DISTINCT: Dies ist äquivalent zu GROUP BY ALL. Lokalität wirkt sich direkt auf die Leistung aus; schlechte Lokalität führt zu langsamen Aktualisierungen.
QUALIFY mit ROW_NUMBER = 1: Snowflake optimiert das Muster QUALIFY ROW_NUMBER() ... = 1, wenn es in der obersten Projektionsebene der dynamischen Tabelle enthalten ist. Dieses Muster wird durchgängig schneller ausgeführt als eine vollständige Aktualisierung.
Die Optimierung funktioniert am besten, wenn alle PARTITION BY- und ORDER BY-Schlüssel in der OVER()-Klausel in der dynamischen Tabelle (in der obersten Projektionsebene enthalten) beibehalten werden.
Empfehlung: Verwenden von QUALIFY anstelle von DISTINCT (wenn möglich)¶
Im folgenden Beispiel wird DISTINCT verwendet:
CREATE DYNAMIC TABLE unique_customers
TARGET_LAG = '1 hour'
WAREHOUSE = my_warehouse
AS
SELECT DISTINCT customer_id, customer_name, email
FROM customer_events;
Im folgenden Beispiel wird QUALIFY verwendet:
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;
Die QUALIFY-Version gibt expliziter an, welches Duplikat aufbewahrt werden soll (das neueste) und funktioniert konstant gut.
Entfernen von redundanten DISTINCT-Operationen¶
Jede DISTINCT-Operation verbraucht bei jeder Aktualisierung Ressourcen. Wenn Ihre Daten bereits eindeutig sind oder Sie Duplikate vorgelagert bereinigen, entfernen Sie unnötige DISTINCT-Klauseln.
Operator-Referenz¶
Die folgende Tabelle erläutert, wie Snowflake die einzelnen SQL-Operatoren während der inkrementellen Aktualisierung verarbeitet:
Operator |
Verarbeitung durch Snowflake |
Leistungshinweise |
|---|---|---|
SELECT |
Wendet Ausdrücke nur auf geänderte Zeilen an. |
Funktioniert gut. Keine besonderen Hinweise. |
WHERE |
Bewertet das Prädikat nur für geänderte Zeilen. |
Funktioniert gut. Die Kosten skalieren linear mit den Änderungen. Hinweis: Ein hochselektiver WHERE-Operator kann Warehouse-Betriebszeit erfordern, auch wenn sich die Ausgabe nicht ändert. |
FROM-<table> |
Durchsucht Mikropartitionen, die Snowflake seit der letzten Aktualisierung hinzugefügt oder entfernt hat. |
Die Kosten skalieren mit dem Volumen der geänderten Partitionen. Begrenzen Sie Änderungen auf etwa fünf Prozent der Quelltabelle. |
UNION ALL |
Übernimmt die Vereinigung der Änderungen von jeder Seite. |
Funktioniert gut. Keine besonderen Hinweise. |
WITH (CTEs) |
Berechnet Änderungen für jeden allgemeinen Tabellenausdruck. |
Funktioniert gut, aber vermeiden Sie zu komplexe Definitionen einzelner Tabellen. Erwägen Sie eine Aufteilung in mehrere dynamische Tabellen. |
Skalare Aggregate |
Berechnet das Aggregat vollständig neu, wenn sich die Eingabe ändert. |
Vermeiden Sie diesen Operator in leistungskritischen Tabellen. Erwägen Sie stattdessen das Gruppieren nach einer Konstante. |
GROUP BY |
Berechnet die Aggregate für geänderte Gruppierungsschlüssel neu. |
Clustern Sie die Quelle nach Gruppierungsschlüsseln. Vermeiden Sie zusammengesetzte Ausdrücke in Schlüsseln. Siehe Optimieren von Aggregationen. |
DISTINCT |
Äquivalent zu GROUP BY ALL. |
Lokalitätsabhängig. Erwägen Sie stattdessen die Verwendung von QUALIFY. Siehe Effizientes Entfernen von Duplikaten (DISTINCT vs. QUALIFY). |
Fensterfunktionen |
Führt eine Neuberechnung für geänderte Partitionsschlüssel durch. |
Schließen Sie immer PARTITION BY ein. Clustern Sie die Quelle nach Partitionsschlüsseln. Siehe Optimieren der Fensterfunktionen. |
INNER JOIN |
Verknüpft Änderungen von jeder Seite mit der anderen Tabelle. |
Funktioniert gut, wenn eine Seite klein ist. Clustern Sie die sich weniger häufig ändernde Seite. Siehe Optimieren von Verknüpfungen. |
OUTER JOIN |
Kombiniert die innere Verknüpfung mit NOT EXISTS-Abfragen für die NULL-Berechnung. |
Am stärksten von der Lokalität abhängiger Operator. Siehe Optimieren von Verknüpfungen. |
LATERAL FLATTEN |
Wendet die flatten-Operation nur auf geänderte Zeilen an. |
Funktioniert gut. Die Kosten skalieren linear mit den Änderungen. |
QUALIFY mit Rangfolge |
Verwendet einen optimierten Pfad für ROW_NUMBER/RANK/DENSE_RANK … = 1 |
Hocheffizient. Platzieren Sie QUALIFY auf der obersten Projektionsebene der dynamischen Tabelle. |