Operationalisierung von Snowpark Python: Teil Eins
In Teil eins dieses Beitrags werden wir einige der einzigartigen Herausforderungen skizzieren, die mit der Einführung von Snowpark-Python-Code in die Produktion verbunden sind, die Komponenten ausführlicher besprechen und einige Code-Designprinzipien skizzieren, die beim Erstellen mit Snowpark Python zu befolgen sind.
In einem zukünftigen zweiten Teil werden wir relevante CI/CD-Konzepte für Python-Entwickler diskutieren, die mit Snowpark Python arbeiten.
Kernherausforderungen
Warum unterscheidet sich die Verwaltung von Snowpark-Code in der Produktion von der Verwaltung von traditionellem/Legacy-Code in der Produktion? In vielerlei Hinsicht ist es das nicht. Wenn Sie bereits mit dem Erstellen von Anwendungen und Funktionen vertraut sind, die von Snowflake unterstützt werden, und Dinge wie gespeicherte Prozeduren, benutzerdefinierte Funktionen usw. verwendet haben (ob SQL oder Snowpark in einer anderen Sprache), dann ist die Verwaltung von Snowpark-Python -Code genau das Richtige nicht grundlegend anders, als Sie die gleiche Arbeit heute erledigen. Es gibt einige Umgebungseinschränkungen für die serverseitige Python-Laufzeit in Snowflake, aber diese ähneln denen, wie Javascript- und Java-Funktionen in Snowpark eingeschränkt sind, und daher gelten dieselben Prinzipien und Praktiken, die Sie für Ihre bestehenden powered by Snowflake-Funktionen befolgen Snowpark-Python.
Die Unterschiede und Herausforderungen werden deutlicher für Teams und Anwendungen, die auf Python, aber nicht auf Snowflake basieren. Auch wenn Snowflake als Datenquelle und/oder Senke innerhalb Ihrer bestehenden Architektur fungiert, weisen Python-Funktionen, die extern zu Snowflake (in serverlosen oder in der Cloud gehosteten VMs usw.) ausgeführt werden, im Vergleich zu denen, die auf Snowpark Python basieren, einige wesentliche Unterschiede auf sich bewusst sein. Im Grunde sind die in Snowpark integrierten Funktionen nur Python-Code, und so viele der gleichen Praktiken und Tools, die Teams heute zur Verwaltung ihrer vorhandenen Codebasen verwenden, sind immer noch relevant. Die Hauptüberlegungen im Zusammenhang mit dem Aufbau auf Snowpark ergeben sich aus der Tatsache, dass der Endcode und die Anwendung in einer vollständig verwalteten SaaS-Plattform bereitgestellt werden. Daher unterliegen die Infrastruktur und die Compute-Frameworks, in denen Ihr Code funktionieren muss, nicht vollständig Ihrer Kontrolle und Ihrem Ermessen. Darüber hinaus ist die Anwendung vollständig in Ihre Datenplattform integriert, was viele Vorteile bietet, aber ein anderes Paradigma darstellt als die meisten Anwendungen, in denen sie entwickelt werden, und daher unterscheiden sich die empfohlenen Entwurfsmuster. Die Bereitstellung von Python-Code in einer SQL-First-Umgebung schränkt auch ein, welche Arten von Daten und wie Daten zwischen Modulen, Funktionen usw. übertragen werden können. Snowpark-Anwendungen unterscheiden sich auch von anderen Anwendungen, die möglicherweise so konzipiert sind, dass sie kontinuierlich ausgeführt werden, 24 /7. Snowpark eignet sich besser für On-Demand- und/oder geplante/koordinierte Jobs und Anwendungen.
Snowpark-Komponenten
Der breite Begriff Snowpark Python bezieht sich auf zwei grundlegend unterschiedliche, aber auch eng gekoppelte Komponenten. Eine davon ist eine Client-Datenrahmen-API, die als Python-Paket verfügbar ist und in jeder Python-Umgebung installiert werden kann (Unterstützung für Python 3.8 ist seit dem 7. November 2022 allgemein verfügbar), die von jeder Python-Anwendung usw. genutzt wird, um Datenrahmen-Transformationen herunterzufahren in Snowflake Compute. Im Gegensatz dazu verfügt Snowpark auch über eine serverseitige Laufzeitumgebung, mit der Sie beliebigen Python-Code in einer von Snowflake verwalteten Laufzeitumgebung bereitstellen können, die direkt neben Ihren Daten ausgeführt wird. Es gibt verschiedene Mechanismen, wie Python-Code in der serverseitigen Laufzeit bereitgestellt und ausgeführt werden kann, auf die weiter unten näher eingegangen wird. Diese Unterscheidung ist wichtig, weil Während es gemeinsame Herausforderungen gibt, die für Snowpark Python allgemein angegangen werden sollten, hat jede dieser Komponenten auch spezifische und einzigartige Herausforderungen, die wir in diesem Dokument ansprechen werden. Im Allgemeinen beziehen wir uns auf Snowpark Python, um beide Komponenten allgemein zu umfassen, die Client- und/oder Dataframe-API, um auf die installierbare Python-Bibliothek zu verweisen, und die serverseitige Laufzeit, um auf die von Snowflake verwaltete Python-Ausführungsumgebung zu verweisen. In diesem Beitrag werden wir die Kernkomponenten zusammenfassen, aber Sie sollten sich auf die beziehen und die serverseitige Laufzeit, um auf die von Snowflake verwaltete Python-Ausführungsumgebung zu verweisen. In diesem Beitrag werden wir die Kernkomponenten zusammenfassen, aber Sie sollten sich auf die beziehen und die serverseitige Laufzeit, um auf die von Snowflake verwaltete Python-Ausführungsumgebung zu verweisen. In diesem Beitrag werden wir die Kernkomponenten zusammenfassen, aber Sie sollten sich auf die beziehenSnowpark Developer Guide for Python für zusätzliche Details, Codebeispiele, Dokumentation und mehr.
Client-Dataframe-API
Die Snowpark-Client-Dataframe-API ist eine Python-Bibliothek, die in jeder Umgebung installiert werden kann, in der Sie einen Python-Kernel ausführen können, und die eine Verbindung zu Ihrem Snowflake-Konto hat (Hinweis: Derzeit ist die Dataframe-API nur mit Python 3.8 kompatibel). Die Dataframe-API bietet Python-Syntax im Dataframe-Stil zum Durchführen von Pushdowns von Abfragen, Transformationen und mehr in die verwaltete Rechenumgebung von Snowflake.
Grundsätzlich bietet die Snowpark-API entsprechende Python-Methoden für gängige SQL-Operationen in einer mit der PySpark Dataframe-API vertrauten Syntax, mit erheblichen Funktionsüberschneidungen zu dem, was Sie heute in PySpark tun können. Es ist wichtig zu beachten, dass Snowpark im Vergleich zu PySpark eine grundlegend andere Back-End-Rechen-Engine verwendet, aber syntaktisch und funktional der PySpark Dataframe-API sehr ähnlich ist und sich auch so anfühlt. Die API arbeitet mit Snowpark Dataframes, die Zeiger auf Tabellen, Ansichten usw. innerhalb von Snowflake sind. Die entsprechenden Operationen für einen Snowpark-API-Aufruf werden träge in einem virtuellen Snowflake-Warenhaus ausgeführt. Dies bedeutet, dass neinSnowpark-Dataframe-Operationen werden direkt in der Rechenumgebung des Python-Clients ausgeführt, sodass die Rechenanforderungen des Clients extrem gering sein können. Snowpark bietet auch bequeme Methoden, um Snowpark-Datenrahmen als Pandas-Datenrahmen in den Speicher des Clients zu bringen und umgekehrt (Pandas-Datenrahmen zurück in Snowflake zu schreiben). Die Snowpark-API erfordert, dass sich die Quelldaten in Snowflake befinden, um ein Pushdown von Transformationen in ein Snowflake Virtual Warehouse durchzuführen. Zusätzlich zu Methoden, die SQL-Operationen entsprechen, enthält die Snowpark-API weitere Hilfsfunktionen sowie die Möglichkeit, serverseitige Snowpark-Python-Objekte (UD(T)Fs und Sprocs, die unten ausführlicher beschrieben werden) von einem Python-Client aus aufzurufen Laufzeit.
UD(T)Fs und gespeicherte Prozeduren
Die serverseitige Python-Laufzeit von Snowpark ermöglicht das Schreiben von gespeicherten Python-Prozeduren und benutzerdefinierten (Tabellen-)Funktionen (UD(T)Fs), die in Snowflake bereitgestellt werden, von jeder Snowflake-Schnittstelle aus aufgerufen und in einer gesicherten, Python-Sandbox in virtuellen Snowflake-Warenhäusern.
Python-UDFs und -UDTFs skalieren die mit dem zugrunde liegenden Python-Code verknüpfte Verarbeitung, sodass sie parallel über alle Threads und Knoten hinweg erfolgt, aus denen das virtuelle Warehouse besteht, auf dem die Funktion ausgeführt wird. Es gibt drei verschiedene UDF-artige Mechanismen mit Snowpark Python:
- Benutzerdefinierte Funktionen (UDF) sind Eins-zu-Eins-Skalaroperationen: Für eine Reihe von Eingabedaten, die an die Funktion übergeben werden, wird eine einzelne Ausgabe erzeugt. Datenzeilen werden parallel über Python-Prozesse auf jedem Knoten innerhalb eines virtuellen Warenhauses verarbeitet.
- Vektorisierte/Batch-UDFs sind ähnlich Eins-zu-Eins-Skalaroperationen wie die oben beschriebenen UDFs. Der Unterschied besteht darin, dass UDFs die Operationen der UDF auf einzelnen Datenzeilen parallelisieren . Vektorisierte UDFs parallelisieren die UDF-Operation für Batchesvon Daten (mehrere Zeilen). Funktional erzeugen vektorisierte UDFs immer noch eine einzelne Ausgabe für jede Eingabezeile von Daten, die Daten werden jedoch in einzelne Instanzen der UDF gestapelt (viele Zeilen werden gleichzeitig übergeben und viele Stapel werden parallel verarbeitet). Der Grund dafür ist, dass viele auf Pandas, Numpy, scipy usw. basierende Python-Operationen, die in Python-UDFs verwendet werden können, für die Ausführung als Operationen im Vektorstil optimiert sind. Wenn einzelne Zeilen wie in einer Standard-UDF verarbeitet werden, nutzt die UDF die Array-basierten Optimierungen, die in die zugrunde liegenden Python-Bibliotheken integriert sind, nicht vollständig aus. Mit vektorisierten UDFs können Sie dies tun; Sie sind funktional die gleichen wie normale Python-UDFs, jedoch werden Daten gestapelt und in großen Mengen verarbeitet, um die Vorteile von Array-basierten Optimierungen in verschiedenen gängigen Python-Bibliotheken zu nutzen.
- Benutzerdefinierte Tabellenfunktionen (UDTFs) sind Python-Funktionen, die zustandsbehaftete Operationen für Datenstapel erfordern. Vektorisierte UDFs stapeln Daten nach dem Zufallsprinzip für eine optimalere, schnellere Verarbeitung, sie erlauben dem Benutzer/Entwickler jedoch nicht zu bestimmen, welche Daten gestapelt werden und wie der gesamte Datenstapel verarbeitet wird: nur einzelne Zeilen. UDTFs ermöglichen eine Viele-zu-Viele- und Viele-zu-Eins-Zeilenverarbeitung. Jede UDTF hat eine process-Methode und eine endPartition-Methode. Die Prozessmethode definiert, welche Arbeit als einzelne Zeilen ausgeführt wirdin einem Batch verarbeitet werden (abhängig von der zugrunde liegenden Funktionalität können Sie eine Ausgabe pro Zeile zurückgeben oder auch nicht). Die endPartition-Methode definiert, welche Arbeit für den gesamten Datenstapel nach der Verarbeitung aller einzelnen Zeilen ausgeführt wird, und kann eine Art zustandsbehaftete Arbeit enthalten, die während der Verarbeitung des Stapels aufgebaut wurde. Wenn UDTFs aufgerufen werden, können Sie mit dem Partition-by- Ausdruck angeben, welche Felder in den zugrunde liegenden Daten zum Stapeln der Daten verwendet werden, dh wenn Sie nach COUNTRY partitionieren , werden alle Datensätze mit COUNTRY=US im selben Stapel verarbeitet, alle Datensätze mit COUNTRY=CHINA werden im selben Batch verarbeitet usw.
Zusätzlich zu UD(T)Fs bietet die serverseitige Runtime von Snowpark Python Unterstützung für gespeicherte Python-Prozeduren. Gespeicherte Prozeduren können als eher willkürliches Skript betrachtet werden, das in einem virtuellen Snowflake-Warenhaus ausgeführt wird. Ein wesentlicher Unterschied besteht darin, dass gespeicherte Prozeduren Einzelknoten sind; Um Transformationen oder Analysen von Daten in großem Umfang innerhalb einer gespeicherten Prozedur durchzuführen, sollten gespeicherte Prozesse daher die Client-Datenrahmen-API oder andere bereitgestellte UD(T)Fs nutzen, um die entsprechende Berechnung über alle Knoten eines virtuellen Warenhauses hinweg zu skalieren. Dies steht im Gegensatz zum Ziehen aller Daten aus einer Abfrage indie gespeicherte Prozedur und deren Manipulation zB mit Pandas. Skalieren Sie stattdessen die Berechnung über das virtuelle Warenlager von einer gespeicherten Prozedur aus, indem Sie die Datenrahmen-API und UD(T)Fs für rechenintensivere Arbeiten nutzen. Dies wird im folgenden Codeentwurfsprinzip weiter veranschaulicht: Sie sollten vermeiden, Daten so weit wie möglich direkt in eine gespeicherte Prozedur zu ziehen (mit einigen Ausnahmen: Dies wird später in diesem Artikel ausführlicher beschrieben). Was gespeicherte Prozeduren jedoch bieten, ist eine einfache Möglichkeit, einen skriptähnlichen Programmablauf in der serverseitigen Runtime von Snowpark bereitzustellen, der als Job über Tasks oder direkte SQL-Anweisungen „CALL sproc“ „gestartet“ werden kann.
Code-Design
Design-Prinzipien
- Das Leitprinzip für den Aufbau von Betriebsfähigkeiten mit Snowpark Python besteht darin, keine Daten aus Snowflake zu ziehen und sie nach Möglichkeit in einer Client-Umgebung zu verarbeiten . Nutzen Sie stattdessen die Dataframe-API des Snowpark-Clients zum Pushdown von SQL-ähnlichen Vorgängen und die serverseitige Laufzeit, um willkürlicheren Code als UD(T)Fs bereitzustellen, der über virtuelle Snowflake-Warehouses hinweg skaliert und Daten effizienter verarbeiten kann. Dies kann als eine ähnliche Programmierpraxis betrachtet werden wie das Herunterdrücken von SQL über JDBC in anderen Tools oder Anwendungen.
- Verwenden Sie die Snowpark-Client-Dataframe-API in Ihren Anwendungen, wenn Sie Daten abfragen und transformieren, anstatt alle Daten in eine Client-Anwendung zu holen und dort zu verarbeiten. Dies kann Ihre Datentransformationen effektiv skalieren, unabhängig davon, ob die gesamte Anwendung innerhalb der serverseitigen Laufzeitumgebung von Snowpark oder in einer externen Python-Umgebung von Snowflake ausgeführt wird. Es ist erwähnenswert, dass Sie SQL direkt verwenden können , anstatt die Datenrahmen-API zu verwenden. Viele Entwickler finden es jedoch umständlich, SQL innerhalb einer Anwendung zu schreiben und zu verwenden, die in einer anderen Sprache geschrieben ist, während die Datenrahmen-API eine vertraute Python-Syntax bietet die gleichen Ergebnisse im Maßstab.
- Code, der Daten manipuliert, analysiert oder transformiert, sollte im größtmöglichen Umfang als UD(T)Fs erstellt werden (die Entscheidung zwischen UDF und UDTF hängt weitgehend davon ab, was der Code/die Transformation tatsächlich tut) oder sollte es sein implementiert mit der Snowpark-Client-Dataframe-API. Dies liegt daran, dass die Datenrahmen-API und UD(T)Fs es Ihnen ermöglichen, die Rechenarbeit zu skalieren und zu parallelisieren, die im gesamten virtuellen Warehouse ausgeführt wird.
- Python Sprocs eignen sich am besten für die Ablaufsteuerung von Python-Programmen. Stellen Sie sich das Sproc als das Hauptskript oder die Hauptanwendung vor – es initialisiert Objekte, verwaltet den Status usw. Innerhalb des Sprocs sollte jede datenintensive Berechnung die Datenrahmen-API aufrufen oder UD(T)Fs verwenden, die separat erstellt und bereitgestellt wurden. Ähnlich wie beim obigen Prinzip „keine Daten an den Client extrahieren“ sollten Sie im Allgemeinen vermeiden, Daten in den Speicher der gespeicherten Prozedur zu ziehen, da dies Ihre Skalierbarkeit einschränkt. Schieben Sie stattdessen die im Sproc ausgeführte Arbeit mithilfe der Datenrahmen-API und UD(T)Fs in das virtuelle Warenlager. Der Sproc kann als „Arbeitseinheit“ innerhalb Ihrer Anwendung betrachtet werden, die Sie mithilfe von Aufgaben oder einem externen Orchestrierungsdienst (z. B. Airflow) orchestrieren können.
- Nur um es noch einmal zu betonen: Sie sollten es so weit wie möglich vermeiden, Daten direkt in den Sproc zu ziehen. Sprocs sind auf die Ausführung auf einem einzelnen Knoten im virtuellen Warenhaus beschränkt und somit auf die Rechenressourcen dieses Knotens beschränkt. Snowpark-optimierte Warehouses (jetzt in Public Preview) erweitern die Fähigkeit von Sprocs, mehr speicher-/datenintensive Arbeit auszuführen, aber als Faustregel sollten Sprocs nicht damit beauftragt werden, signifikante Berechnungen selbst durchzuführen, und innerhalb eines Sprocs sollten Sie dies tun Auslagern von Arbeit an die Snowpark-API und/oder UD(T)Fs.
- Die Ausnahme von Prinzip 5 ist eine Berechnung, die nicht auf verteilte Weise durchgeführt werden kann und für deren Durchführung der Zugriff auf einen gesamten Datensatz (oder eine große Stichprobe) erforderlich ist. Beispielsweise sollte das Modelltraining für maschinelles Lernen mit einem einzelnen Knoten im Allgemeinen im Kontext einer gespeicherten Prozedur durchgeführt werden, aber dies ist ein seltenes Beispiel, bei dem datenintensive Berechnungen in einer gespeicherten Prozedur durchgeführt werden sollten. Ohne zu sehr ins Detail zu gehen, kann es Anwendungsfälle rund um das Modelltraining geben, in denen die Parallelisierung über UD(T)Fs sinnvoll ist, aber dies ist eine kleine und spezifische Gruppe von Anwendungsfällen.
- Die Standardprinzipien für das Design von Python-Code sollten in Bezug auf die Modularität des Codes, die Wiederverwendbarkeit usw. befolgt werden. Es empfiehlt sich, häufig verwendete Dienstprogramme als benutzerdefinierte Paketabhängigkeit von Drittanbietern in Ihre Anwendung zu integrieren, damit der Code einmal entwickelt/gewartet werden kann potenziell in Ihrem gesamten Ökosystem von Snowpark-Anwendungen genutzt werden.
- Benutzerdefinierte Klassen und Objekte, die Sie in Ihrer gesamten Anwendung verwenden, müssen auf Kompatibilität mit UD(T)Fs geprüft werden. Beispiel: Angenommen, Sie haben einen Teil Ihrer Anwendung, der eine Reihe von Daten aufnimmt, einige Analysen dazu durchführt und dann ein benutzerdefiniertes Python-Klassenobjekt basierend auf der Ausgabe Ihrer Analyse erstellt. Dies ist potenziell gut für eine UDTF geeignet, wir unterstützen jedoch nicht die Rückgabe beliebiger Python-Objekte aus Snowpark-Funktionen. Daher müssen Sie Serialisierungs-/Deserialisierungsmethoden Ihres Objekts für unterstützte SQL-Datentypen berücksichtigen, z. B. die Implementierung von to_json()- und from_json()-Konstruktoren/Serialisierern, damit Sie Ihre Klassenobjekte aus Snowflake-Tabellendaten initialisieren können. Sie können auch eine binäre Serialisierung in Betracht ziehen – unabhängig vom Ansatz muss dies berücksichtigt werden.
- Instanzen von UD(T)Fs werden innerhalb eines einzelnen Abfragesatzes wiederverwendet. Sie können dies ausnutzen, indem Sie Initialisierungscode oder Variablen/temporären Zustand verschieben, der über Ausführungen hinweg außerhalb der Funktionsmethode wiederverwendet werden kann, und in den globalen/statischen Teil des Codes verschoben werden. Dies bedeutet, dass bei nachfolgenden Ausführungen diese Variablen oder der temporäre Zustand wiederverwendet werden könnten, ohne jede einzelne Ausführung neu initialisieren zu müssen. Dies ist besonders wichtig, wenn Dinge wie externer Zugriff verfügbar werden, bei denen Sie HTTP-Clients oder Verbindungspools außerhalb der Funktionsdeklaration platzieren möchten (siehe AWS Lambda / Azure Functions für ähnliche Entwurfsmuster und Best Practices).
- Mit vektorisierten (Batch-)UDFs können Sie die gleichen Operationen wie mit UDFs ausführen, während Sie die Vorteile von Pythons eigenen internen Array-basierten Optimierungen für Pandas- und Numpy-Objekte nutzen (dies wird oben ausführlicher beschrieben). Als Faustregel gilt im Allgemeinen die bewährte Vorgehensweise, UDFs als vektorisierte UDFs bereitzustellen, wenn einer der zugrunde liegenden Vorgänge für die Daten auf Numpy/Pandas basiert oder mithilfe von Vektorvorgängen implementiert wird. Dadurch wird einfach die Datenverteilung an die serverseitige Laufzeit optimiert und Snowpark kann die integrierten Python-Optimierungen nutzen.
- Zusätzlich zu den eigenen Caching-Ebenen von Snowflake sollte der Snowpark-Python-Code im Allgemeinen den Best Practices für das Python-Caching folgen, mit der Ausnahme, dass Abfrageergebnisse zwischengespeichert werden müssen (da Snowflake dies auf verschiedenen Ebenen in der Architektur für Sie erledigt). Wenn Sie jedoch beispielsweise eine UDF haben, die Text-Tokenisierung in Ihrer Anwendung durchführt, und um sie zu verwenden, müssen Sie einen erstellten Tokenizer aus der Phase laden, sollten Sie eine Funktion umschließen, die den Tokenizer mithilfe von Cachetools in die UDF lädt, um Wiederholungen zu vermeiden Laden des Tokenizers von der Stufe in die UDF. Dies ist der häufigste Anwendungsfall für das Caching innerhalb von Snowpark-Code – wenn ein Artefakt aus der Phase in ein UD(T)F geladen werden muss.
Portierung bestehender Anwendungen zu Snowpark
Viele Kunden haben gefragt, wie sie vorhandene Funktionen und Anwendungen für die Ausführung in Snowpark portieren können, um sowohl die Skalierbarkeit, Leistung, Governance und Sicherheit zu verbessern als auch ihre Architektur zu vereinfachen und die mit dem Besitz und der Verwaltung der Infrastruktur verbundene Komplexität zu beseitigen. Über die anfängliche Bewertung „Kann diese Anwendung und/oder dieser Code von Snowpark unterstützt werden?“ hinaus sollte es ausführliche Diskussionen und Gespräche darüber geben, wie Code am besten übertragen werden kann. Im Falle der Migration von PySpark-Anwendungen speziell zu Snowpark (im Gegensatz zu anderen allgemeineren Python-Apps) ist Snowflake eine Partnerschaft mit Mobilize.net eingegangenum ein kostenloses Codeanalysetool von PySpark zu Snowpark bereitzustellen, mit dem festgestellt werden kann, ob Ihre vorhandene Codebasis ein guter Kandidat für die Migration zu Snowpark ist. Darüber hinaus können die Professional Services-Teams und SI-Partner von Snowflake vollständigen Migrationssupport bieten.
Bei allgemeineren Python-Anwendungen könnten Python-Skripte dies tun just be dropped into Python sprocs and are likely to more or less “work,” but this is likely to be an extremely inefficient implementation, unless the particular script is computationally light. In particular, these existing applications are likely pulling data out of Snowflake, which as we emphasize above, is not the recommended pattern for building applications on Snowpark. The two primary questions to consider are (1) how does code that extracts data from Snowflake need to be refactored to leverage more compute push-down. Additionally, (2) Data intensive applications especially need to be evaluated to determine what functions, methods, classes, etc. are better served by leveraging Python UD(T)Fs and taking advantage of scalability and performance in Virtual Warehouses. Existing Python applications may not inherently follow the above code design principles, and so assessments should be performed to identify how to refactor into a code design that fits these principles without introducing a significant amount of overhead and friction.
Neben der reinen Codeanalyse besteht ein weiterer Ansatz zur Durchführung dieser Migrationsbewertung darin, mit einer Codebasis zu beginnen und ein logisches Flussdiagramm der Anwendung/des Skripts zu erstellen, das in einzelne Rechenkomponenten aufgeteilt ist. Viele Teams verfügen möglicherweise bereits über diese Art von Softwaredesign/Archdiagramm, aber wenn nicht, ist es ein guter Anfang, um zu verstehen, wie Daten und Rechenarbeit in Ihrer Anwendung verteilt sind. Dieses Diagramm kann auch benutzerdefinierte Klassenobjekte usw. enthalten. Für jede verwendete Funktion, Klasse und Methode sollten Sie auswerten, welche Daten bereitgestellt werden müssen und welche Ausgabe erzeugt wird. Ist die Ausgabe mit Snowflake-Datentypen kompatibel? Wofür wird der Output verbraucht und wie wird er verwendet? Ist die durchgeführte Berechnung intensiv genug, um die Ausführung auf einem Cluster von Rechenknoten in einem virtuellen Warenhaus zu rechtfertigen? Wie viel benutzerdefinierte Konfiguration ist bei jeder Iteration der Verwendung der Funktion/des Objekts erforderlich?
Durch das Ausfüllen dieses Diagramms wird deutlich, was in der logischen Flussschicht der Anwendung vorhanden sein sollte (die möglicherweise gut zu einem Snowpark-Python-Sproc passt) und was auf ein UD(T)F ausgelagert werden muss , und somit möglicherweise umgestaltet. Dies zeigt Ihnen auch, welche benutzerdefinierten Klassen und Objekte über Serialisierungsmethoden zum Schreiben in/Initialisieren aus der Snowpark-Tabellenstruktur verfügen müssen, wie in den Designprinzipien oben beschrieben.
Von diesem Punkt an können Sie beginnen zu verstehen, welcher Code aufgehoben und verschoben werden kann und welcher Code umgestaltet, neu implementiert oder geändert werden muss. Darüber hinaus bietet Snowflake Professional Services Angebote für mehr praktische Unterstützung bei der Migration von Anwendungen zu Snowpark, die über Prinzipien und Best Practices hinausgehen.
Fazit
In diesem Beitrag haben wir detailliert beschrieben, was Snowpark Python ist (Client-Dataframe-API und serverseitige Laufzeit) und wie es am besten in Python-Anwendungen verwendet werden kann. Wir haben grundlegende Designprinzipien skizziert, die beim Entwerfen oder Migrieren von Anwendungen für Snowpark Python befolgt werden sollten. In Teil zwei werden wir untersuchen, wie diese neuen Funktionen in bestehende CI/CD- und DevOps-Praktiken integriert werden können, einschließlich der Frage, wie sich Snowpark Python von anderen Entwicklungs-Frameworks sowohl ähneln als auch stark voneinander unterscheiden kann.

![Was ist überhaupt eine verknüpfte Liste? [Teil 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































