Práticas recomendadas para funções externas

Este tópico documenta as práticas recomendadas que melhorarão a eficiência e evitarão resultados inesperados que podem ocorrer se um serviço remoto não for projetado para ser compatível com o Snowflake.

Você pode encontrar outras práticas recomendadas nos seguintes documentos:

Neste tópico:

Usar uma API de lote de serviço remoto se disponível

Alguns serviços remotos oferecem tanto o modo de lote quanto o modo de linha única. Se for esperado que as consultas que utilizam uma função externa enviem várias linhas, então o Snowflake recomenda usar o modo de lote do serviço remoto para melhorar o desempenho.

Essa regra não se aplica necessariamente se:

  • Cada linha for muito grande (por exemplo, centenas de quilobytes ou mais).

  • O serviço remoto processar linhas de forma diferente quando são recebidas em lotes e quando são recebidas individualmente. (Para obter mais detalhes, consulte Processar uma linha por vez.)

Processar uma linha por vez

Para minimizar a sobrecarga da rede, o Snowflake geralmente envia linhas em lotes para serviços remotos. O número de lotes e o tamanho de cada lote pode variar.

Além disso, a ordem dos lotes pode variar, e a ordem das linhas dentro de um lote pode variar. Mesmo que a consulta contenha uma cláusula ORDER BY, o ORDER BY é normalmente aplicado após a chamada das funções externas.

Como o tamanho do lote e a ordem das linhas não são garantidos, escrever uma função que retorna um valor para uma linha que depende de qualquer outra linha nesse lote ou em lotes anteriores pode produzir resultados não determinísticos.

O Snowflake recomenda enfaticamente que o serviço remoto processe cada linha de forma independente. O valor de retorno para cada linha de entrada deve depender apenas daquela linha de entrada, não de outras linhas de entrada. (Atualmente, as funções externas não oferecem suporte a funções de janela, por exemplo).

Observe também que, como o tamanho do lote não é garantido, a contagem dos lotes não é significativa.

Consulte também Garantir que sua função externa não tenha monitoração de estado.

Não presumir que cada linha é passada para o serviço remoto somente uma vez

Se o Snowflake chama um serviço remoto, e o serviço remoto recebe a solicitação e retorna um resultado, mas o Snowflake não recebe o resultado devido a um problema temporário na rede, o Snowflake pode repetir a solicitação. Se o Snowflake fizer uma nova tentativa, o serviço remoto poderá ver a mesma linha duas vezes (ou mais).

Isso pode causar efeitos inesperados. Por exemplo, como o serviço remoto pode ser chamado mais de uma vez para o mesmo valor, um serviço remoto que atribui IDs únicas pode ter lacunas na sequência dessas IDs. Em alguns casos, tais efeitos podem ser reduzidos pelo rastreamento da ID de lote no campo sf-external-function-query-batch-id do cabeçalho da solicitação para determinar se um determinado lote de linhas foi processado anteriormente. Quando o Snowflake faz uma nova solicitação para um lote específico, o Snowflake usa a mesma ID de lote que usou anteriormente para o mesmo lote.

O Snowflake faz uma nova tentativa quando recebe os seguintes erros:

  • Todos os erros transitórios de transporte na rede.

  • Todas as solicitações que falham com código de status 429.

  • Todas as solicitações que falham com código de status 5XX.

As solicitações são tentadas novamente até que seja alcançado um tempo limite de novas tentativas. O tempo limite total de novas tentativas não é configurável pelo usuário. O Snowflake pode ajustar esse limite no futuro.

Quando o tempo limite total de nova tentativa é alcançado sem uma nova tentativa bem-sucedida, a consulta falha.

Se sua chamada de função externa expirar quando o serviço remoto estiver funcionando, e todos os elementos entre o Snowflake e o serviço remoto parecerem estar funcionando, você pode tentar um tamanho de lote menor para ver se isso reduz os erros de tempo limite.

Para saber como definir o tamanho máximo do lote, consulte CREATE EXTERNAL FUNCTION.

Garantir que sua função externa não tenha monitoração de estado

Em geral, uma função externa (incluindo o serviço remoto) deve evitar o armazenamento de informações de estado para os dois casos:

  • Estado interno (estado que o serviço remoto armazena internamente).

  • Estado externo (estado armazenado fora do serviço remoto, por exemplo, informações de estado enviadas para outro serviço remoto ou lidas de outro serviço remoto que por si só retém o estado).

Se o serviço remoto mudar as informações de estado e depois usar essas informações para afetar as saídas futuras, a função pode retornar valores diferentes dos esperados.

Por exemplo, considere um simples serviço remoto que contém um contador interno e retorna o número de linhas recebidas desde o início do serviço remoto. Se houver um problema temporário na rede, e o Snowflake repetir uma solicitação com os mesmos dados, o serviço remoto contará as linhas reenviadas duas vezes (ou mais).

Para um exemplo envolvendo estado externo, consulte Evitar efeitos colaterais.

Nos raros casos em que uma função não é sem estado, a documentação para os chamadores deve dizer claramente que a função é sem estado, e a função deve ser marcada como volátil.

Se um serviço remoto trata solicitações de forma assíncrona, então o autor do serviço remoto deve escrever o serviço remoto para armazenar e gerenciar algum estado temporariamente. Por exemplo, o serviço remoto deve armazenar a ID de lote da solicitação HTTP POST para que, se um HTTP GET for recebido com a mesma ID de lote, o serviço remoto possa retornar o código HTTP 202 quando o lote especificado ainda estiver sendo processado.

Note que uma consulta pode ser anulada por vários motivos, o que significa que não há garantia de que um GET final chegará após o serviço remoto ter terminado de gerar um resultado. Os serviços remotos que armazenam o estado para solicitações assíncronas devem, em algum momento, expirar e limpar esse estado interno. O tempo limite ideal pode mudar no futuro, mas atualmente o Snowflake recomenda preservar as informações sobre solicitações assíncronas por pelo menos 10 minutos e de preferência 12 horas antes de apagá-las.

Evitar efeitos colaterais

Uma função externa (incluindo o serviço remoto) deve evitar efeitos colaterais, como mudança do estado externo (informações armazenadas fora do serviço remoto).

Por exemplo, se o serviço remoto reporta valores fora do intervalo a uma agência governamental, isso é um efeito colateral.

Efeitos colaterais podem ser úteis, mas os efeitos colaterais de chamar uma função externa nem sempre são previsíveis. Por exemplo, suponha que você chame um serviço remoto que analisa um registro de saúde anônimo e retorna um diagnóstico. Suponha também que se o diagnóstico demonstrar que o paciente tem uma doença contagiosa, então o diagnóstico é relatado a uma agência que monitora a contagem do número de casos dessa doença. Esse é um efeito colateral útil. No entanto, é vulnerável a problemas como:

  • Se uma chamada de função externa está dentro de uma transação que é revertida, os efeitos colaterais não são revertidos.

  • Se o serviço remoto for chamado mais de uma vez com a mesma linha (por exemplo, devido a falhas temporárias na rede e novas tentativas), o efeito colateral pode ocorrer mais de uma vez. Por exemplo, um paciente infectado pode ser contado duas vezes nas estatísticas.

Há também situações em que as linhas podem ser contadas a menos, e não a mais.

Nos casos muito raros em que uma função tem efeitos colaterais, a documentação para chamadores deve dizer claramente quais são os efeitos colaterais, e a função deve ser marcada como volátil.

Categorizar sua função como volátil ou imutável

As funções podem ser categorizadas como voláteis ou imutáveis. (A instrução CREATE EXTERNAL FUNCTION permite ao usuário especificar se a função é volátil ou imutável).

Para que uma função externa seja considerada imutável, ela deve satisfazer os seguintes critérios:

  • Se for dado o mesmo valor de entrada, a função retorna o mesmo valor de saída. (Por exemplo, a função SQRT retorna a mesma saída quando dada a mesma entrada, mas a função CURRENT_TIMESTAMP não retorna necessariamente a mesma saída quando dada a mesma entrada).

  • A função não tem efeitos colaterais. (Para obter mais detalhes, consulte Evitar efeitos colaterais.)

Se uma função atende a esses dois critérios, o Snowflake pode usar certos tipos de otimização para reduzir o número de linhas ou lotes enviados para o serviço remoto. (Essas otimizações podem evoluir com o tempo e não são descritas em detalhes aqui).

O Snowflake não pode detectar ou aplicar a imutabilidade ou fatores que afetam a imutabilidade (por exemplo, efeitos colaterais). O redator de um serviço remoto deve documentar se o serviço remoto atende aos critérios para ser rotulado como imutável. Se um serviço remoto tiver efeitos colaterais, então a função externa que chama esse serviço remoto deve ser marcada como volátil, mesmo que a chamada de função retorne o mesmo valor de saída para o mesmo valor de entrada. Se você não tem certeza de que um serviço remoto é imutável, qualquer função externa que chame esse serviço remoto deve ser rotulada de volátil.

Considerar erros de tempo limite

Uma chamada de função externa envolve o Snowflake, um serviço remoto, um serviço de proxy e, potencialmente, outros elementos da cadeia. Nenhum desses elementos sabe quanto tempo uma determinada chamada de função deve levar, portanto nenhum sabe exatamente quando parar de esperar e retornar um erro de tempo limite. Cada etapa pode ter seu próprio tempo limite independente. Para obter mais informações sobre tempo limite e novas tentativas, consulte Considerar erros de tempo limite e novas tentativas.

Minimizar a latência

Para minimizar a latência e melhorar o desempenho das chamadas de funções externas, o Snowflake recomenda fazer o seguinte, quando for prático:

  • Coloque o API Gateway na mesma plataforma de nuvem e região das instâncias do Snowflake que a chamam com mais frequência (ou com a maior quantidade de dados).

  • Se você escreveu o serviço remoto (em vez de usar um serviço existente), implante esse serviço remoto na mesma plataforma de nuvem e região a partir das quais ele é chamado.

  • Envie o mínimo possível de dados. Por exemplo, se o serviço remoto examinar os valores de entrada e operar somente em um subconjunto deles, então geralmente é mais eficiente filtrar em SQL e enviar somente as linhas relevantes ao serviço remoto, em vez de enviar todas as linhas ao serviço remoto e deixá-lo filtrar.

    Como outro exemplo, se você estiver processando uma coluna que contém grandes valores de dados semiestruturados, e o serviço remoto operar somente em uma pequena parte de cada um desses valores de dados, normalmente é mais eficiente extrair a parte relevante usando o SQL Snowflake e enviar somente essa parte, em vez de enviar a coluna inteira e fazer com que o serviço remoto faça a extração da parte antes do processamento.

Desenvolver e testar as funções externas uma etapa por vez

O Snowflake recomenda que você teste sem o Snowflake antes de testar com o Snowflake.

Durante os primeiros estágios de desenvolvimento de uma função externa, use o console de serviço de proxy da plataforma de nuvem (por exemplo, o console do Amazon API Gateway) e o console de desenvolvimento de serviço remoto (por exemplo, o console do AWS Lambda) para ajudar a desenvolver e testar o serviço proxy e o serviço remoto.

Por exemplo, se você desenvolveu uma função Lambda, você pode testá-la extensivamente usando o console Lambda antes de testá-la chamando-a no Snowflake.

Os testes no console de serviço de proxy e no console de serviço remoto geralmente têm as seguintes vantagens:

  • Podem facilitar o diagnóstico do problema porque há menos lugares para procurar a causa do problema.

  • A exibição da carga de dados pode fornecer informações úteis para a depuração. O Snowflake não mostra nenhuma parte da carga de dados em mensagens de erro; embora isso aumente a segurança, pode retardar a depuração.

  • O Snowflake faz uma nova tentativa automática de erros HTTP 5xx, o que pode tornar a depuração mais lenta ou mais difícil em algumas situações.

  • Os testes pelo Snowflake consomem créditos Snowflake, além dos créditos da plataforma de nuvem.

Claro que, depois de testar o serviço remoto e o serviço de proxy o máximo possível sem o Snowflake, você deve testá-los com o Snowflake. As vantagens de testar com o Snowflake incluem:

  • Você testa todas as etapas envolvidas na função externa.

  • A utilização de uma tabela Snowflake como fonte de dados facilita o teste com grandes volumes de dados para obter uma estimativa realista do desempenho da função externa.

Considere os seguintes casos de teste:

  • Valores NULL.

  • Valores “vazios” (por exemplo, cadeias de caracteres vazias, tipos de dados semiestruturados vazios).

  • Valores VARCHAR e BINARY muito longos, se apropriado.

Tornar seu serviço remoto assíncrono

Se você está escrevendo um serviço remoto, e se seu serviço remoto pode não retornar resultados dentro do tempo limite esperado, então considere tonar seu serviço remoto assíncrono. Para obter mais detalhes, consulte Serviços remotos assíncronos vs. síncronos.

Assegurar que os argumentos para a função externa correspondem aos argumentos analisados pelo serviço remoto

Ao passar argumentos de ou para uma função externa, certifique-se de que os tipos de dados sejam apropriados. Se o valor enviado não se encaixar no tipo de dados recebido, o valor pode estar truncado ou corrompido, ou a chamada do serviço remoto pode falhar.

Por exemplo, como alguns tipos de dados do SQL Snowflake podem armazenar valores maiores do que os tipos de dados JavaScript normalmente utilizados, a desserialização de grandes números do JSON é particularmente delicada em JavaScript.

Se você alterar o número, tipos de dados ou a ordem dos argumentos para o serviço remoto, lembre-se de fazer as alterações correspondentes na função externa. Atualmente, o comando ALTER FUNCTION não tem a opção de alterar os parâmetros, portanto, é preciso descartar e recriar a função externa para alterar os argumentos.