O suporte ao UDF escalar paralelo é uma solicitação de recurso razoável?

10

Está bastante bem documentado que a UDF escalar força um plano serial geral.

Executando funções em paralelo

Dado um grande número de linhas que chegam a um ponto no pipeline em que uma UDF deve ser calculada, por que o mecanismo não pode apenas distribuí-las entre os processadores? Se não houver estado dentro de uma UDF, o pedido não será importante.

Há alegações de que a UDF é uma caixa preta e deve usar o cursor. Percebo que um cursor de usuário não pode ser paralelizado em um SP para os casos em que algum estado é mantido entre iterações, mas parece que deveria ser paralelamente possível.

Pontos extras para explicar por que o mecanismo força todo o plano a ser serial, em vez de apenas o estágio de cálculo da UDF.

O suporte para UDF paralelo é um recurso razoável a ser solicitado?

crokusek
fonte
11
A reação apropriada parece ser, conforme observado na resposta aceita no seu link, reescrever quaisquer Funções Escalares Definidas pelo Usuário como Funções com Valor de Tabela Inline de coluna única . Eles são expandidos da mesma maneira que uma visualização e, portanto, são totalmente otimizados. Sob esse prisma, sua pergunta ainda tem mérito?
Pieter Geerkens
11
Sim em caso de sucesso com a solução alternativa do TVF. Eu perguntei porque parece errado evitar o uso de uma construção tão natural. Também parece impraticável esperar que novos desenvolvedores de SQL aprendam internamente UDF.
22414 crokusek
Comentário esclarecedor. Sucesso com o ITVF, mas não com o TVF com várias instruções.
26414 crokusek

Respostas:

17

Está bastante bem documentado que as UDFs forçam um plano serial geral.

Não tenho certeza de que tudo esteja bem documentado.

  • Uma função escalar T-SQL evita o paralelismo em qualquer lugar do plano.
  • Uma função CLR escalar pode ser executada em paralelo, desde que não acesse o banco de dados.
  • Uma função T-SQL com valor de tabela com várias instruções força uma zona serial em um plano que pode usar paralelismo em outro lugar.
  • Uma função T-SQL embutida com valor de tabela é expandida como uma visualização, portanto, não tem efeito direto.

Consulte Forçando um plano de execução paralela e / ou a apresentação de Execução Paralela de Craig Freedman .

Há alegações de que as UDFs são uma caixa preta e devem usar o cursor.

Essas alegações não estão corretas.

Pontos extras para explicar por que o mecanismo força todo o plano a ser serial, em vez de apenas o estágio de cálculo da UDF.

Meu entendimento é que as restrições atuais são puramente o resultado de certos detalhes de implementação. Não há razão fundamental para que funções não possam ser executadas usando paralelismo.

Especificamente, as funções escalares do T-SQL são executadas em um contexto T-SQL separado, o que complica a operação, coordenação e desligamento corretos (especialmente no caso de um erro) significativamente.

Da mesma forma, as variáveis ​​de tabela suportam leituras paralelas (mas não gravam) em geral, mas a variável de tabela exposta por uma função com valor de tabela não é capaz de suportar leituras paralelas por razões específicas da implementação. Você precisaria de alguém com acesso ao código fonte (e a liberdade de compartilhar detalhes) para fornecer uma resposta autorizada, receio.

O suporte para UDF paralelo é um recurso razoável a ser solicitado?

Obviamente, se você puder argumentar com força suficiente. Minha opinião é de que o trabalho envolvido seria extenso, portanto sua proposta teria que atender a um nível extremamente alto. Por exemplo, uma solicitação relacionada (e muito mais simples) para fornecer funções escalares em linha tem grande suporte, mas permanece deficiente por anos.


Você pode ler o documento da Microsoft:

... que descreve a abordagem que a Microsoft está adotando para resolver os problemas de desempenho da função escalar T-SQL na versão após o SQL Server 2017.

O objetivo do Froid é permitir que os desenvolvedores usem as abstrações de UDFs e procedimentos sem comprometer o desempenho. Froid atinge esse objetivo usando uma nova técnica para converter automaticamente programas imperativos em formas algébricas relacionais equivalentes sempre que possível. O Froid modela blocos de código imperativo como expressões relacionais e os combina sistematicamente em uma única expressão usando o operador Apply, permitindo que o otimizador de consultas escolha planos de consulta paralelos eficientes, orientados a conjuntos .

(ênfase minha)


As funções T-SQL escalares em linha agora são implementadas no SQL Server 2019 .

Paul White 9
fonte
11

Como Paulo mencionou corretamente em sua resposta, não há razão fundamental para que UDFs escalares não possam ser executados usando paralelismo. No entanto, além dos desafios de implementação, há outro motivo para forçá-los a serem seriais. O artigo Froid citado por Paul fornece mais informações sobre isso.

Citando o artigo (Seção 2.3):

Atualmente, o SQL Server não usa paralelismo intra-consulta em consultas que invocam UDFs. Os métodos podem ser projetados para mitigar essa limitação, mas apresentam desafios adicionais, como escolher o grau certo de paralelismo para cada chamada da UDF.

Por exemplo, considere um UDF que chama outras consultas SQL, como a da Figura 1. Cada uma dessas consultas pode usar paralelismo e, portanto, o otimizador não tem como saber como compartilhar threads entre eles, a menos que examine o UDF e decide o grau de paralelismo de cada consulta dentro (o que pode potencialmente mudar de uma chamada para outra). Com UDFs aninhadas e recursivas, esse problema se torna ainda mais difícil de gerenciar.

A abordagem do Froid, conforme descrito no artigo, não resultará apenas em planos paralelos, mas também adiciona muito mais benefícios para consultas com UDFs. Em essência, ele inclui seu pedido de execução paralela de UDFs.

Atualização: O Froid agora está disponível como um recurso da visualização do SQL Server 2019. O recurso é chamado "Scalar UDF Inlining". Mais detalhes aqui: https://blogs.msdn.microsoft.com/sqlserverstorageengine/2018/11/07/introducing-scalar-udf-inlining/

[Divulgação: Eu sou co-autor do artigo Froid]

Karthik
fonte
Muito bom! Se eu entendi corretamente, ele efetivamente converterá o UDF em um ITVF internamente. Fizemos isso por alguns (w / declara / if / else) e fizemos uma bela bagunça. Até tivemos uma "coluna" de depuração.
crokusek
11
Na verdade, ele não converte o UDF em um ITVF, mas sua intuição está correta. Fazer isso manualmente no nível da consulta SQL é realmente complicado para UDFs complexos. Froid faz essa transformação na árvore álgebra relacional, o que evita a bagunça :)
Karthik
@Karthik, você pode dar uma olhada em dba.stackexchange.com/questions/202211/… . Eu realmente gostaria de saber como Froid vai realizar no caso descrito
Roman Pekar
@ Roman Eu comentei sua pergunta.
Karthik
11
Obrigado, @Karthik, pelo trabalho que você fez no artigo da Froid e pelos seus esforços (e dos grupos) para melhorar a usabilidade das UDFs escalares :-) #
485 Solomon Rutzky