Meilleures pratiques pour les fonctions externes

Ce sujet documente les meilleures pratiques qui permettront d’améliorer l’efficacité et de prévenir les résultats inattendus qui pourraient se produire si un service à distance n’est pas conçu pour être compatible avec Snowflake.

Vous pouvez trouver d’autres meilleures pratiques dans les documents suivants :

Dans ce chapitre :

Utiliser une API de lot d’un service à distance si disponible

Certains services à distance offrent à la fois le mode par lot et le mode à une seule ligne. Si les requêtes qui utilisent une fonction externe sont censées envoyer plusieurs lignes, alors Snowflake recommande d’utiliser le mode lot du service à distance pour améliorer les performances.

Cette règle ne s’applique pas nécessairement si :

  • Chaque ligne est très grande (par exemple, des centaines de kilo-octets ou plus).

  • Le service à distance traite les lignes différemment si elles sont reçues par lots que si elles sont reçues individuellement. (Pour plus de détails, voir Traiter une ligne à la fois.)

Traiter une ligne à la fois

Pour réduire les frais de mise en réseau, Snowflake regroupe généralement les lignes à envoyer aux services distants. Le nombre de lots et la taille de chaque lot peuvent varier.

En outre, l’ordre des lots peut varier et l’ordre des lignes d’un lot peut varier. Même si la requête contient une clause ORDER BY, le ORDER BY est généralement appliqué après l’appel de la ou des fonctions externes.

Etant donné que la taille du lot et l’ordre des lignes ne sont pas garantis, l’écriture d’une fonction qui renvoie une valeur pour une ligne qui dépend de toute autre ligne de ce lot ou des lots précédents peut produire des résultats non déterministes.

Snowflake recommande fortement que le service distant traite chaque ligne indépendamment. La valeur de retour pour chaque ligne d’entrée doit dépendre uniquement de cette ligne d’entrée, pas des autres lignes d’entrée. (Actuellement, les fonctions externes ne prennent pas en charge les fonctions de fenêtre, par exemple.)

Notez également que la taille des lots n’étant pas garantie, le comptage des lots n’est pas significatif.

Voir aussi Assurez-vous que votre fonction externe est Stateless.

Ne supposez pas que le service distant a validé chaque ligne exactement une fois

Si Snowflake appelle un service distant et que le service distant reçoit la demande et renvoie un résultat, mais Snowflake ne reçoit pas le résultat en raison d’un problème de réseau temporaire, Snowflake peut répéter la demande. Si Snowflake réessaie, le service distant peut voir la même ligne deux fois (ou plus).

Cela peut provoquer des effets inattendus. Par exemple, étant donné que le service distant peut être appelé plusieurs fois pour la même valeur, un service distant qui affecte des IDs uniques peut présenter des lacunes dans la séquence de ces IDs. Dans certains cas, ces effets peuvent être réduits en suivant l” ID de lot dans le champ sf-external-function-query-batch-id de l’en-tête de la requête afin de déterminer si un lot de lignes particulier a été traité précédemment. Lorsque Snowflake réitère une requête pour un lot spécifique, Snowflake utilise le même ID de lot que celui qu’il a utilisé précédemment pour le même lot.

Snowflake réessaie lorsqu’il reçoit les erreurs suivantes :

  • Toutes les erreurs de transport de réseau transitoires.

  • Toutes les demandes qui échouent avec le code de statut 429.

  • Toutes les demandes qui échouent avec le code de statut 5XX.

Les requêtes sont réessayées jusqu’à ce qu’un délai de relance total soit atteint. Le délai total de relance n’est pas configurable par l’utilisateur. Snowflake pourrait ajuster cette limite à l’avenir.

Lorsque le délai d’expiration total des tentatives est atteint sans nouvelle tentative, la requête échoue.

Si votre appel de fonction externe expire lorsque le service distant fonctionne et que tous les éléments entre Snowflake et le service distant semblent fonctionner, vous pouvez essayer une taille de lot plus petite pour voir si cela réduit les erreurs de délai d’attente.

Pour savoir comment définir la taille de lot maximale, voir CREATE EXTERNAL FUNCTION.

Assurez-vous que votre fonction externe est Stateless

En général, une fonction externe (y compris le service distant) devrait éviter de stocker des informations d’état, à la fois :

  • Etat interne (indiquer que le service distant effectue un stockage en interne).

  • Etat externe (état stocké en dehors du service distant, par exemple des informations d’état envoyées à et/ou lues à partir d’un autre service distant qui lui-même conserve l’état).

Si le service distant modifie les informations d’état et utilise ensuite ces informations pour affecter les sorties futures, la fonction peut renvoyer des valeurs différentes de celles attendues.

Par exemple, considérons un service distant simple qui contient un compteur interne et renvoie le nombre de lignes reçues depuis le premier démarrage du service distant. S’il y a un problème de réseau temporaire et que Snowflake répète une demande avec les mêmes données, le service distant comptera les lignes renvoyées deux fois (ou plus).

Pour un exemple impliquant un état externe, voir Evitez les effets secondaires.

Dans les rares cas où une fonction n’est pas Stateless, la documentation pour les appelants doit indiquer clairement que la fonction n’est pas Stateless et que la fonction doit être marquée comme volatile.

Si un service distant traite les demandes de manière asynchrone, alors l’auteur du service distant doit écrire le service distant pour stocker et gérer temporairement un certain état. Par exemple, le service à distance doit stocker l” ID de lot de la requête HTTP POST de sorte que si une requête HTTP GET est reçue avec le même ID de lot, le service à distance peut renvoyer le code HTTP 202 lorsque le lot spécifié est encore en cours de traitement.

Notez qu’une requête peut être interrompue pour diverses raisons, ce qui signifie qu’il n’y a aucune garantie qu’un GET final arrivera après que le service à distance ait fini de générer un résultat. Les services à distance qui stockent l’état des requêtes asynchrones devraient éventuellement expirer et nettoyer cet état interne. Le délai d’expiration optimal pourrait changer à l’avenir, mais actuellement Snowflake recommande de conserver les informations relatives aux requêtes asynchrones pendant au moins 10 minutes et de préférence 12 heures avant de les supprimer.

Evitez les effets secondaires

Une fonction externe (y compris le service distant) devrait éviter les effets secondaires, tels que le changement d’état externe (informations stockées en dehors du service distant).

Par exemple, si le service distant signale des valeurs hors limites à une agence gouvernementale, cela est un effet secondaire.

Les effets secondaires peuvent être utiles, mais les effets secondaires de l’appel d’une fonction externe ne sont pas toujours prévisibles. Par exemple, supposons que vous appeliez un service distant qui analyse un dossier de santé anonyme et renvoie un diagnostic. Supposons également que si le diagnostic est que le patient a une maladie contagieuse, alors le diagnostic est signalé à une agence qui tient compte du nombre de cas de cette maladie. Ceci est un effet secondaire utile. Cependant, cela est vulnérable à des problèmes tels que les suivants :

  • Si un appel de fonction externe se trouve dans une transaction annulée, les effets secondaires ne sont pas annulés.

  • Si le service distant est appelé plusieurs fois avec la même ligne (par exemple, en raison de pannes de réseau temporaires et de nouvelles tentatives), l’effet secondaire peut se produire plusieurs fois. Par exemple, un patient infecté peut être compté deux fois dans les statistiques.

Il existe également des situations dans lesquelles les lignes peuvent être sous-comptées plutôt que sur-comptées.

Dans les très rares cas où une fonction a des effets secondaires, la documentation destinée aux appelants doit indiquer clairement quels sont les effets secondaires et la fonction doit être marquée comme volatile.

Classez votre fonction comme volatile ou immuable

Les fonctions peuvent être classées comme volatiles ou immuables. (L’instruction CREATE EXTERNAL FUNCTION permet à l’utilisateur de spécifier si la fonction est volatile ou immuable.)

Pour qu’une fonction externe soit considérée comme immuable, elle doit répondre aux critères suivants :

  • Si on lui donne la même valeur d’entrée, la fonction renvoie la même valeur de sortie. (Par exemple, la fonction SQRT renvoie la même sortie lorsqu’elle reçoit la même entrée, mais la fonction CURRENT_TIMESTAMP ne renvoie pas nécessairement la même sortie lorsqu’elle reçoit la même entrée.)

  • La fonction n’a aucun effet secondaire. (Pour plus de détails, voir Evitez les effets secondaires.)

Si une fonction répond à ces deux critères, Snowflake peut utiliser certains types d’optimisations pour réduire le nombre de lignes ou de lots envoyés au service distant. (Ces optimisations peuvent évoluer avec le temps et ne sont pas décrites en détail ici.)

Snowflake ne peut pas détecter ou imposer l’immuabilité ou les facteurs qui affectent l’immuabilité (par exemple, les effets secondaires). Le rédacteur d’un service distant doit documenter si le service distant répond aux critères pour être considéré comme immuable. Si un service distant a des effets secondaires, la fonction externe qui appelle ce service distant doit être marquée comme volatile, même si l’appel de fonction renvoie la même valeur de sortie pour la même valeur d’entrée. Si vous n’êtes pas certain qu’un service distant est immuable, toute fonction externe qui appelle ce service distant doit être considérée comme volatile.

Tenir compte des erreurs d’expiration de délai

Un appel de fonction externe implique Snowflake, un service distant, un service proxy et potentiellement d’autres éléments de la chaîne. Aucun de ces éléments ne sait combien de temps un appel de fonction particulier devrait prendre, donc aucun ne sait exactement quand arrêter d’attendre et renvoyer une erreur d’expiration de délai. Chaque étape peut avoir son propre délai d’expiration indépendant. Pour plus d’informations sur les délais d’expiration et les tentatives, voir Tenir compte des erreurs d’expiration de délai et tentatives.

Réduire la latence

Pour réduire la latence et améliorer les performances des appels de fonctions externes, Snowflake recommande de procéder comme suit lorsque cela est possible :

  • Placez API Gateway dans la même plate-forme et région Cloud que les instances Snowflake qui l’appellent le plus souvent (ou avec la plus grande quantité de données).

  • Si vous avez rédigé le service distant (plutôt que d’utiliser un service existant), déployez ce service distant dans la même plate-forme et région Cloud que celle d’où il est appelé.

  • Envoyez le moins de données possible. Par exemple, si le service distant examine les valeurs des entrées et n’opère que sur un sous-ensemble d’entre elles, il est généralement plus efficace de filtrer dans SQL et d’envoyer uniquement les lignes pertinentes au service distant, plutôt que d’envoyer toutes les lignes au service à distance et laisser le filtre opérer.

    Comme autre exemple, si vous traitez une colonne qui contient de grandes valeurs de données semi-structurées et que le service distant ne fonctionne que sur une petite partie de chacune de ces valeurs de données, il est généralement plus efficace d’extraire l’élément pertinent à l’aide de Snowflake SQL et de n’envoyer que cet élément, plutôt que d’envoyer la colonne entière et demander au service distant d’extraire le petit élément avant le traitement.

Développer et tester les fonctions externes - Une étape à la fois

Snowflake vous recommande d’effectuer les tests sans Snowflake avant de tester avec Snowflake.

Pendant les premières étapes du développement d’une fonction externe, utilisez la console de service proxy de la plate-forme Cloud (par exemple, la console Amazon API Gateway) et la console de développement de service à distance (par exemple, la console AWS Lambda) pour aider à développer et tester le service proxy et le service distant.

Par exemple, si vous avez développé une fonction Lambda, vous souhaiterez peut-être la tester de manière approfondie via la console Lambda avant de la tester en l’appelant depuis Snowflake.

Les tests via la console de service proxy et la console de service distante présentent généralement les avantages suivants :

  • Cela peut faciliter le diagnostic du problème car il y a moins d’endroits pour rechercher la cause du problème.

  • L’affichage de la charge utile des données peut fournir des informations de débogage utiles. Snowflake n’affiche aucune partie de la charge utile des données dans les messages d’erreur ; bien que cela améliore la sécurité, cela peut ralentir le débogage.

  • Snowflake réessaie automatiquement les erreurs HTTP 5xx, ce qui peut rendre le débogage plus lent ou plus difficile dans certaines situations.

  • Les tests via Snowflake consomment des crédits Snowflake en plus des crédits de la plate-forme Cloud.

Bien sûr, après avoir testé le service distant et le service proxy autant que possible sans Snowflake, vous devez les tester avec Snowflake. Voici une sélection des avantages des tests avec Snowflake :

  • Vous testez toutes les étapes impliquées dans la fonction externe.

  • L’utilisation d’une table Snowflake comme source de données facilite le test avec de grands volumes de données pour obtenir une estimation réaliste des performances de la fonction externe.

Considérez les cas de test suivants :

  • valeurs NULL.

  • Valeurs « vides » (par exemple, chaînes vides, types de données semi-structurés vides).

  • Valeurs VARCHAR et BINARY très longues, le cas échéant.

Rendre votre service à distance asynchrone

Si vous écrivez un service à distance, et si votre service à distance risque de ne pas renvoyer de résultats dans le délai prévu, envisagez alors de rendre votre service à distance asynchrone. Pour plus de détails, voir Services à distance synchrones et asynchrones.

Assurez-vous que les arguments de la fonction externe correspondent aux arguments analysés par le service distant

Lorsque vous transmettez des arguments vers ou depuis une fonction externe, assurez-vous que les types de données sont appropriés. Si la valeur envoyée ne peut pas correspondre au type de données reçues, la valeur peut être tronquée ou corrompue, ou l’appel de service distant peut échouer.

Par exemple, comme certains types de données numériques Snowflake SQL peuvent stocker des valeurs plus importantes que les types de données JavaScript couramment utilisés, la désérialisation de grands nombres à partir de JSON est particulièrement sensible dans JavaScript.

Si vous modifiez le nombre, les types de données ou l’ordre des arguments dans le service distant, n’oubliez pas d’apporter les modifications correspondantes à la fonction externe. Actuellement, la commande ALTER FUNCTION n’a pas d’option pour modifier les paramètres, vous devez donc supprimer et recréer la fonction externe pour modifier les arguments.