Embutimento de UDF escalarScalar UDF Inlining

APLICA-SE A: simSQL Server nãoBanco de Dados SQL do Azure nãoAzure Synapse Analytics (SQL DW) nãoParallel Data Warehouse APPLIES TO: yesSQL Server noAzure SQL Database noAzure Synapse Analytics (SQL DW) noParallel Data Warehouse

Este artigo apresenta o embutimento de UDF escalar, um recurso sob o conjunto de recursos de Processamento de Consulta Inteligente.This article introduces Scalar UDF Inlining, a feature under the Intelligent Query Processing suite of features. Esse recurso melhora o desempenho das consultas que invocam UDFs escalares em SQL ServerSQL Server (começando com SQL Server 2019 (15.x)SQL Server 2019 (15.x)) e Banco de Dados SQL do AzureAzure SQL Database.This feature improves the performance of queries that invoke scalar UDFs in SQL ServerSQL Server (starting with SQL Server 2019 (15.x)SQL Server 2019 (15.x)) and Banco de Dados SQL do AzureAzure SQL Database.

Funções escalares definidas pelo usuário T-SQLT-SQL scalar User-Defined Functions

UDFs (funções definidas pelo usuário) implementadas no Transact-SQLTransact-SQL e que retornam um valor de dados único são chamadas de Funções Definidas pelo Usuário Escalares T-SQL.User-Defined Functions (UDFs) that are implemented in Transact-SQLTransact-SQL and return a single data value are referred to as T-SQL Scalar User-Defined Functions. UDFs do T-SQL são uma maneira elegante de obter reutilização e modularidade de código em consultas Transact-SQLTransact-SQL.T-SQL UDFs are an elegant way to achieve code reuse and modularity across Transact-SQLTransact-SQL queries. Alguns cálculos (como regras de negócios complexas) são mais fáceis de expressar no formulário de UDF imperativa.Some computations (such as complex business rules) are easier to express in imperative UDF form. UDFs ajudam na criação de uma lógica complexa sem exigir experiência em escrever consultas SQL complexas.UDFs help in building up complex logic without requiring expertise in writing complex SQL queries.

Desempenho de UDFs escalaresPerformance of scalar UDFs

Normalmente, UDFs escalares acabam tendo um desempenho ruim devido aos seguintes motivos:Scalar UDFs typically end up performing poorly due to the following reasons:

  • Invocação iterativa: UDFs são invocados de maneira iterativa, uma vez a cada tupla qualificada.Iterative invocation: UDFs are invoked in an iterative manner, once per qualifying tuple. Isso resulta em custos adicionais repetido de comutação de contexto repetida devido à invocação de função.This incurs additional costs of repeated context switching due to function invocation. Especialmente UDFs que executam consultas Transact-SQLTransact-SQL em sua definição são gravemente afetadas.Especially, UDFs that execute Transact-SQLTransact-SQL queries in their definition are severely affected.

  • Falta de custos: Durante a otimização, somente operadores relacionais terão o custo calculado, enquanto os operadores escalares não terão.Lack of costing: During optimization, only relational operators are costed, while scalar operators are not. Antes da introdução de UDFs escalares, outros operadores escalares geralmente eram baratos e não exigiam avaliação de custo.Prior to the introduction of scalar UDFs, other scalar operators were generally cheap and did not require costing. Um pequeno custo de CPU adicionado para uma operação de escalar foi suficiente.A small CPU cost added for a scalar operation was enough. Há cenários em que o custo real é significativo e ainda assim permanece sub-representado.There are scenarios where the actual cost is significant, and yet still remains underrepresented.

  • Execução interpretada: UDFs são avaliados como um lote de instruções, executados instrução a instrução.Interpreted execution: UDFs are evaluated as a batch of statements, executed statement-by-statement. Cada instrução em si é compilada e o plano compilado é armazenado em cache.Each statement itself is compiled, and the compiled plan is cached. Embora essa estratégia de armazenamento em cache economize algum tempo, pois evita recompilações, cada instrução é executada em isolamento.Although this caching strategy saves some time as it avoids recompilations, each statement executes in isolation. Nenhuma otimização entre instruções é executada.No cross-statement optimizations are carried out.

  • Execução serial: o SQL ServerSQL Server não permite paralelismo dentro da consulta em consultas que invocam UDFs.Serial execution: SQL ServerSQL Server does not allow intra-query parallelism in queries that invoke UDFs.

Embutimento automático de UDFs escalaresAutomatic inlining of scalar UDFs

A meta do recurso de embutimento de UDF escalar é melhorar o desempenho de consultas que invocam UDFs escalares do T-SQL, em que a execução da UDF é o principal gargalo.The goal of the scalar UDF inlining feature is to improve performance of queries that invoke T-SQL scalar UDFs, where UDF execution is the main bottleneck.

Com esse novo recurso, os UDFs escalares são automaticamente transformados em expressões escalares ou subconsultas escalares substituídas na consulta responsável pela chamada, em vez do operador UDF.With this new feature, scalar UDFs are automatically transformed into scalar expressions or scalar subqueries that are substituted in the calling query in place of the UDF operator. Essas expressões e subconsultas então são otimizadas.These expressions and subqueries are then optimized. Como resultado, o plano de consulta não terá mais um operador de função definido pelo usuário, mas seus efeitos serão observados no plano, como modos de exibição ou TVFs embutidos.As a result, the query plan will no longer have a user-defined function operator, but its effects will be observed in the plan, like views or inline TVFs.

Exemplo 1: UDF estado de instrução únicaExample 1 - Single statement scalar UDF

Considere a consulta a seguir.Consider the following query.

SELECT L_SHIPDATE, O_SHIPPRIORITY, SUM (L_EXTENDEDPRICE *(1 - L_DISCOUNT)) 
FROM LINEITEM
INNER JOIN ORDERS
  ON O_ORDERKEY = L_ORDERKEY 
GROUP BY L_SHIPDATE, O_SHIPPRIORITY ORDER BY L_SHIPDATE;

Essa consulta calcula a soma dos preços com desconto para itens de linha e apresenta os resultados agrupados por data de envio e prioridade de envio.This query computes the sum of discounted prices for line items and presents the results grouped by the shipping date and shipping priority. A expressão L_EXTENDEDPRICE *(1 - L_DISCOUNT) é a fórmula para o preço com desconto para um determinado item de linha.The expression L_EXTENDEDPRICE *(1 - L_DISCOUNT) is the formula for the discounted price for a given line item. Essas fórmulas podem ser extraídas em funções para o benefício de modularidade e da reutilização.Such formulas can be extracted into functions for the benefit of modularity and reuse.

CREATE FUNCTION dbo.discount_price(@price DECIMAL(12,2), @discount DECIMAL(12,2)) 
RETURNS DECIMAL (12,2) AS
BEGIN
  RETURN @price * (1 - @discount);
END

Agora, a consulta pode ser modificada para invocar essa UDF.Now the query can be modified to invoke this UDF.

SELECT L_SHIPDATE, O_SHIPPRIORITY, SUM (dbo.discount_price(L_EXTENDEDPRICE, L_DISCOUNT)) 
FROM LINEITEM
INNER JOIN ORDERS
  ON O_ORDERKEY = L_ORDERKEY 
GROUP BY L_SHIPDATE, O_SHIPPRIORITY ORDER BY L_SHIPDATE

Devido a motivos descritos anteriormente, a consulta com a UDF tem um mau desempenho.Due to the reasons outlined earlier, the query with the UDF performs poorly. Agora, com o embutimento de UDF escalar, a expressão escalar no corpo da UDF é substituída diretamente na consulta.Now, with scalar UDF inlining, the scalar expression in the body of the UDF is substituted directly in the query. Os resultados da execução dessa consulta são mostrados na tabela a seguir:The results of running this query are shown in the below table:

Consulta:Query: Consulta sem UDFQuery without UDF Consultar com UDF (sem embutimento)Query with UDF (without inlining) Consultar com embutimento de UDF escalarQuery with scalar UDF inlining
Tempo de execução:Execution time: 1,6 segundo1.6 seconds 29 minutos e 11 segundos29 minutes 11 seconds 1,6 segundo1.6 seconds

Esses números são baseados em um banco de dados CCI de 10 GB (usando o esquema do TPC-H), em execução em um computador com processador duplo (12 núcleos), 96 GB de RAM, apoiado por SSD.These numbers are based on a 10-GB CCI database (using the TPC-H schema), running on a machine with dual processor (12 core), 96-GB RAM, backed by SSD. Os números incluem a compilação e o tempo de execução com um pool de buffers e cache de procedimento frio.The numbers include compilation and execution time with a cold procedure cache and buffer pool. A configuração padrão foi usada e nenhum outro índice foi criado.The default configuration was used, and no other indexes were created.

Exemplo 2: UDF escalar de várias instruçõesExample 2 - Multi-statement scalar UDF

UDFs escalares implementadas usando várias instruções T-SQL, como atribuições de variáveis e ramificação condicional, também podem ser embutidos.Scalar UDFs that are implemented using multiple T-SQL statements such as variable assignments and conditional branching can also be inlined. Considere a seguinte UDF escalar que, dada uma chave de cliente, determina a categoria de serviço para esse cliente.Consider the following scalar UDF that, given a customer key, determines the service category for that customer. Ele chega na categoria computando primeiro o preço total de todos os pedidos feitos pelo cliente usando uma consulta SQL.It arrives at the category by first computing the total price of all orders placed by the customer using a SQL query. Então, ela usa uma lógica IF (...) ELSE para decidir a categoria com base no preço total.Then, it uses an IF (...) ELSE logic to decide the category based on the total price.

CREATE OR ALTER FUNCTION dbo.customer_category(@ckey INT) 
RETURNS CHAR(10) AS
BEGIN
  DECLARE @total_price DECIMAL(18,2);
  DECLARE @category CHAR(10);

  SELECT @total_price = SUM(O_TOTALPRICE) FROM ORDERS WHERE O_CUSTKEY = @ckey;

  IF @total_price < 500000
    SET @category = 'REGULAR';
  ELSE IF @total_price < 1000000
    SET @category = 'GOLD';
  ELSE 
    SET @category = 'PLATINUM';

  RETURN @category;
END

Agora, considere uma consulta que invoque essa UDF.Now, consider a query that invokes this UDF.

SELECT C_NAME, dbo.customer_category(C_CUSTKEY) FROM CUSTOMER;

O plano de execução para essa consulta no SQL Server 2017 (14.x)SQL Server 2017 (14.x) (nível de compatibilidade 140 e anterior) é o seguinte:The execution plan for this query in SQL Server 2017 (14.x)SQL Server 2017 (14.x) (compatibility level 140 and earlier) is as follows:

Plano de consulta sem embutimento

Como mostra o plano, o SQL ServerSQL Server adota uma estratégia simples aqui: para cada tupla na tabela CUSTOMER, invoca a UDF e produz os resultados.As the plan shows, SQL ServerSQL Server adopts a simple strategy here: for every tuple in the CUSTOMER table, invoke the UDF and output the results. Essa estratégia é ingênua e ineficiente.This strategy is naive and inefficient. Com embutimento, essas UDFs são transformadas em subconsultas escalares equivalentes, que são substituídas na consulta responsável pela chamada no lugar da UDF.With inlining, such UDFs are transformed into equivalent scalar subqueries, which are substituted in the calling query in place of the UDF.

Para a mesma consulta, o plano com a UDF embutida se parece com o abaixo.For the same query, the plan with the UDF inlined looks as below.

Plano de consulta com embutimento

Como mencionado anteriormente, o plano de consulta não tem mais um operador de função definida pelo usuário, mas seus efeitos agora são observáveis no plano, como modos de exibição ou TVFs embutidos.As mentioned earlier, the query plan no longer has a user-defined function operator, but its effects are now observable in the plan, like views or inline TVFs. Aqui estão algumas observações importantes do plano de acima:Here are some key observations from the above plan:

  • O SQL ServerSQL Server inferiu a junção implícita entre CUSTOMER e ORDERS e tornou isso explícito por meio de um operador de junção.SQL ServerSQL Server has inferred the implicit join between CUSTOMER and ORDERS and made that explicit via a join operator.
  • O SQL ServerSQL Server também inferiu o GROUP BY O_CUSTKEY on ORDERS implícito e usou IndexSpool + StreamAggregate para implementá-lo.SQL ServerSQL Server has also inferred the implicit GROUP BY O_CUSTKEY on ORDERS and has used the IndexSpool + StreamAggregate to implement it.
  • O SQL ServerSQL Server agora está usando o paralelismo em todos os operadores.SQL ServerSQL Server is now using parallelism across all operators.

Dependendo da complexidade da lógica na UDF, o plano de consulta resultante também poderá ficar maior e mais complexo.Depending upon the complexity of the logic in the UDF, the resulting query plan might also get bigger and more complex. Como podemos ver, as operações dentro da UDF agora não são mais uma caixa preta e, portanto, o otimizador de consulta é capaz de calcular o custo e otimizar essas operações.As we can see, the operations inside the UDF are now no longer a black box, and hence the query optimizer is able to cost and optimize those operations. Além disso, uma vez que a UDF não está mais no plano, invocação da UDF iterativa é substituída por um plano que evita completamente a sobrecarga de chamada de função.Also, since the UDF is no longer in the plan, iterative UDF invocation is replaced by a plan that completely avoids function call overhead.

Requisitos de UDFs escalares que podem ser embutidasInlineable scalar UDFs requirements

Uma UDF T-SQL escalar poderá ser embutida se todas as seguintes condições forem verdadeiras:A scalar T-SQL UDF can be inline if all of the following conditions are true:

  • A UDF é escrita usando as seguintes construções:The UDF is written using the following constructs:
    • DECLARE, SET: Declaração de variável e atribuições.DECLARE, SET: Variable declaration and assignments.
    • SELECT: Consulta SQL com atribuições variáveis únicas/múltiplas1.SELECT: SQL query with single/multiple variable assignments1.
    • IF/ELSE: Ramificação com níveis arbitrários de aninhamento.IF/ELSE: Branching with arbitrary levels of nesting.
    • RETURN: Instruções de retorno únicas ou múltiplas.RETURN: Single or multiple return statements.
    • UDF: Chamadas de função aninhadas/recursivas2.UDF: Nested/recursive function calls2.
    • Outros: Operações relacionais, como EXISTS, ISNULL.Others: Relational operations such as EXISTS, ISNULL.
  • A UDF não invoca nenhuma função intrínseca que seja dependente de tempo (como GETDATE()) ou tenha efeitos colaterais3 (como NEWSEQUENTIALID()).The UDF does not invoke any intrinsic function that is either time-dependent (such as GETDATE()) or has side effects3 (such as NEWSEQUENTIALID()).
  • A UDF usa a cláusula EXECUTE AS CALLER (o comportamento padrão se a cláusula EXECUTE AS não for especificada).The UDF uses the EXECUTE AS CALLER clause (the default behavior if the EXECUTE AS clause is not specified).
  • A UDF não faz referência a variáveis de tabela nem parâmetros com valor de tabela.The UDF does not reference table variables or table-valued parameters.
  • A consulta que invoca uma UDF escalar não faz referência a uma chamada UDF escalar em sua cláusula GROUP BY.The query invoking a scalar UDF does not reference a scalar UDF call in its GROUP BY clause.
  • A consulta que invoca um UDF escalar em sua lista de seleção com a cláusula DISTINCT não tem a cláusula ORDER BY.The query invoking a scalar UDF in its select list with DISTINCT clause does not have ORDER BY clause.
  • O UDF não é usado na cláusula ORDER BY.The UDF is not used in ORDER BY clause.
  • A UDF não é compilada nativamente (há suporte para interoperabilidade).The UDF is not natively compiled (interop is supported).
  • A UDF não é usada em uma coluna computada nem em uma definição de restrição de verificação.The UDF is not used in a computed column or a check constraint definition.
  • A UDF não faz referência a tipos definidos pelo usuário.The UDF does not reference user-defined types.
  • Não há assinaturas adicionadas à UDF.There are no signatures added to the UDF.
  • A UDF não é uma função de partição.The UDF is not a partition function.

1 SELECT com acúmulo/agregação variável (por exemplo, SELECT @val += col1 FROM table1) não há suporte para embutimento.1 SELECT with variable accumulation/aggregation (for example, SELECT @val += col1 FROM table1) is not supported for inlining.

2 UDFs recursivos serão embutidos em uma profundidade determinada apenas.2 Recursive UDFs will be inlined to a certain depth only.

3 Funções intrínsecas cujos resultados dependem da hora do sistema atual são dependente de hora.3 Intrinsic functions whose results depend upon the current system time are time-dependent. Uma função intrínseca que pode atualizar algum estado global interno é um exemplo de uma função com efeitos colaterais.An intrinsic function that may update some internal global state is an example of a function with side effects. Essas funções retornam resultados diferentes cada vez que são chamadas, com base no estado interno.Such functions return different results each time they are called, based on the internal state.

Verificar se uma UDF pode ser embutida ou nãoChecking whether or not a UDF can be inlined

Para cada UDF escalar do T-SQL, a exibição de catálogo sys.sql_modules inclui uma propriedade chamada is_inlineable, que indica se uma UDF pode ser embutida ou não.For every T-SQL scalar UDF, the sys.sql_modules catalog view includes a property called is_inlineable, which indicates whether a UDF is inlineable or not.

Observação

A propriedade is_inlineable é derivada dos constructos encontrados na definição da UDF.The is_inlineable property is derived from the constructs found inside the UDF definition. Ele não verifica se a UDF é, na verdade, embutível em tempo de compilação.It does not check whether the UDF is in fact inlineable at compile time. Para obter mais informações, confira as condições de inlining.For more information, see the conditions for inlining.

Um valor de 1 indica que ele é pode ser embutido e 0 indica o contrário.A value of 1 indicates that it is inlineable, and 0 indicates otherwise. Essa propriedade terá um valor de 1 para todos as TVFs embutidos também.This property will have a value of 1 for all inline TVFs as well. Para todos os outros módulos, o valor será 0.For all other modules, the value will be 0.

Se uma UDF escalar puder ser embutida, isso não implica que ele sempre será embutido.If a scalar UDF is inlineable, it does not imply that it will always be inlined. O SQL ServerSQL Server decidirá qual (por consulta, por UDF) se embutirá uma UDF ou não.SQL ServerSQL Server will decide (on a per-query, per-UDF basis) whether to inline a UDF or not. Alguns exemplos de quando um UDF não pode ser embutido incluem:A few examples of when a UDF may not be inlined include:

  • Se a definição da UDF for executada em milhares de linhas de código, o SQL ServerSQL Server poderá optar por não embuti-la.If the UDF definition runs into thousands of lines of code, SQL ServerSQL Server might choose not to inline it.

  • Uma invocação de UDF em uma cláusula GROUP BY não será embutida.A UDF invocation in a GROUP BY clause will not be inlined. Essa decisão é tomada quando a consulta que referencia uma UDF escalar é compilada.This decision is made when the query referencing a scalar UDF is compiled.

  • Se a UDF for assinada com um certificado.If the UDF is signed with a certificate. Como as assinaturas podem ser adicionadas e descartadas após a criação de uma UDF, a decisão de embutir ou não é feita quando a consulta que faz referência a uma UDF escalar é compilada.Because signatures could be added and dropped after a UDF has been created, the decision of whether to inline or not is done when the query referencing a scalar UDF is compiled. Por exemplo, as funções do sistema normalmente são assinadas com um certificado.For example, system functions are typically signed with a certificate. Você pode usar sys. crypt_properties para localizar quais objetos são assinados.You can use sys.crypt_properties to find which objects are signed.

    SELECT * 
    FROM sys.crypt_properties AS cp
    INNER JOIN sys.objects AS o ON cp.major_id = o.object_id;
    

Verificar se embutimento ocorreu ou nãoChecking whether inlining has happened or not

Se todas as pré-condições forem atendidas e o SQL ServerSQL Server decidir executar embutimento, ele transformará a UDF em uma expressão relacional.If all the preconditions are satisfied and SQL ServerSQL Server decides to perform inlining, it transforms the UDF into a relational expression. Do plano de consulta, é fácil descobrir se embutimento ocorreu ou não:From the query plan, it is easy to figure out whether inlining has happened or not:

  • O xml do plano não terá um nó xml <UserDefinedFunction> para uma UDF que tenha sido embutida com êxito.The plan xml will not have a <UserDefinedFunction> xml node for a UDF that has been inlined successfully.
  • Determinados XEvents são emitidos.Certain XEvents are emitted.

Como habilitar o embutimento de UDF escalarEnabling Scalar UDF Inlining

Você pode qualificar automaticamente as cargas de trabalho para embutimento de UDF escalar habilitando o nível de compatibilidade 150 para o banco de dados.You can make workloads automatically eligible for Scalar UDF Inlining by enabling compatibility level 150 for the database. Você pode definir isso usando Transact-SQLTransact-SQL.You can set this using Transact-SQLTransact-SQL. Por exemplo:For example:

ALTER DATABASE [WideWorldImportersDW] SET COMPATIBILITY_LEVEL = 150;

Além disso, não há nenhuma outra alteração que precise ser feita para consultas ou UDFs para aproveitar esse recurso.Apart from this, there are no other changes required to be made to UDFs or queries to take advantage of this feature.

Como desabilitar o embutimento de UDF escalar sem alterar o nível de compatibilidadeDisabling Scalar UDF Inlining without changing the compatibility level

O embutimento de UDF escalar pode ser desabilitado no escopo da UDF, da instrução ou do banco de dados enquanto ainda mantém o nível de compatibilidade do banco de dados 150 e superior.Scalar UDF inlining can be disabled at the database, statement, or UDF scope while still maintaining database compatibility level 150 and higher. Para desabilitar o embutimento de UDF escalar no escopo do banco de dados, execute a seguinte instrução dentro do contexto do banco de dados aplicável:To disable scalar UDF inlining at the database scope, execute the following statement within the context of the applicable database:

ALTER DATABASE SCOPED CONFIGURATION SET TSQL_SCALAR_UDF_INLINING = OFF;

Para habilitar novamente o embutimento de UDF escalar para o banco de dados, execute a seguinte instrução dentro do contexto do banco de dados aplicável:To re-enable Scalar UDF Inlining for the database, execute the following statement within the context of the applicable database:

ALTER DATABASE SCOPED CONFIGURATION SET TSQL_SCALAR_UDF_INLINING = ON;

Quando LIGADA, essa configuração aparecerá como habilitada em sys.database_scoped_configurations.When ON, this setting will appear as enabled in sys.database_scoped_configurations. Você também pode desabilitar o embutimento de UDF escalar de uma consulta específica designando DISABLE_TSQL_SCALAR_UDF_INLINING como uma dica de consulta USE HINT.You can also disable Scalar UDF Inlining for a specific query by designating DISABLE_TSQL_SCALAR_UDF_INLINING as a USE HINT query hint. Por exemplo:For example:

SELECT L_SHIPDATE, O_SHIPPRIORITY, SUM (dbo.discount_price(L_EXTENDEDPRICE, L_DISCOUNT)) 
FROM LINEITEM
INNER JOIN ORDERS
  ON O_ORDERKEY = L_ORDERKEY 
GROUP BY L_SHIPDATE, O_SHIPPRIORITY ORDER BY L_SHIPDATE
OPTION (USE HINT('DISABLE_TSQL_SCALAR_UDF_INLINING'));

Uma dica de consulta USE HINT tem precedência sobre a configuração no escopo do banco de dados ou a configuração de nível de compatibilidade.A USE HINT query hint takes precedence over the database scoped configuration or compatibility level setting.

O embutimento de UDF escalar também pode ser desabilitado para uma UDF específica usando a cláusula INLINE na instrução CREATE FUNCTION ou ALTER FUNCTION.Scalar UDF Inlining can also be disabled for a specific UDF using the INLINE clause in the CREATE FUNCTION or ALTER FUNCTION statement. Por exemplo:For example:

CREATE OR ALTER FUNCTION dbo.discount_price(@price DECIMAL(12,2), @discount DECIMAL(12,2))
RETURNS DECIMAL (12,2)
WITH INLINE = OFF
AS
BEGIN
    RETURN @price * (1 - @discount);
END;

Depois que a declaração acima é executada, essa UDF nunca será embutida em nenhuma consulta que a invoque.Once the above statement is executed, this UDF will never be inlined into any query that invokes it. Para habilitar novamente o embutimento para essa UDF, execute a seguinte instrução:To re-enable inlining for this UDF, execute the following statement:

CREATE OR ALTER FUNCTION dbo.discount_price(@price DECIMAL(12,2), @discount DECIMAL(12,2))
RETURNS DECIMAL (12,2)
WITH INLINE = ON
AS
BEGIN
    RETURN @price * (1 - @discount);
END

Observação

A cláusula INLINE não é obrigatória.The INLINE clause is not mandatory. Se a cláusula INLINE não for especificada, ela será automaticamente definida como ON/OFF com base em se a UDF pode ser embutida.If INLINE clause is not specified, it is automatically set to ON/OFF based on whether the UDF can be inlined. Se INLINE = ON for especificado, mas a UDF for considerada não qualificada para embutimento, um erro será gerado.If INLINE = ON is specified but the UDF is found ineligible for inlining, an error will be thrown.

Observações importantesImportant Notes

Conforme descrito neste artigo, o embutimento de UDF escalar transforma uma consulta com UDFs escalares em uma consulta com uma subconsulta escalar equivalente.As described in this article, scalar UDF inlining transforms a query with scalar UDFs into a query with an equivalent scalar subquery. Devido a essa transformação, os usuários podem observar algumas diferenças no comportamento nos seguintes cenários:Due to this transformation, users may notice some differences in behavior in the following scenarios:

  1. O embutimento resultará em um hash de consulta diferente para o mesmo texto da consulta.Inlining will result in a different query hash for the same query text.
  2. Determinados avisos em instruções dentro da UDF (como divisão por zero etc.) que podem ter sido ocultados anteriormente, pode aparecer devido ao embutimento.Certain warnings in statements inside the UDF (such as divide by zero etc.) which might have been hidden earlier, might show up due to inlining.
  3. Dicas de junção no nível da consulta talvez não sejam válidas, pois o embutimento pode introduzir novas junções.Query level join hints might not be valid anymore, as inlining may introduce new joins. Dicas de junção local precisarão ser usadas em vez disso.Local join hints will have to be used instead.
  4. Exibições que referenciam UDFs embutidos escalares não podem ser indexadas.Views that reference inline scalar UDFs cannot be indexed. Se você precisar criar um índice nessas exibições, desabilite embutimento para UDFs referenciadas.If you need to create an index on such views, disable inlining for the referenced UDFs.
  5. Pode haver algumas diferenças no comportamento de Máscara de Dados Dinâmicos com embutimento de UDF.There might be some differences in the behavior of Dynamic Data masking with UDF inlining. Em certas situações (dependendo da lógica na UDF), embutimento pode ser mais conservador no que diz respeito ao mascaramento de colunas de saída.In certain situations (depending upon the logic in the UDF), inlining might be more conservative w.r.t masking output columns. Em cenários em que as colunas referenciadas em uma UDF não são colunas de saída, elas não são mascaradas.In scenarios where the columns referenced in a UDF are not output columns, they will not be masked.
  6. Se uma UDF referenciar funções internas, como SCOPE_IDENTITY(), @@ROWCOUNT ou @@ERROR, o valor retornado pela função interna será alterado com o inlining.If a UDF references built-in functions such as SCOPE_IDENTITY(), @@ROWCOUNT, or @@ERROR, the value returned by the built-in function will change with inlining. Essa alteração no comportamento ocorre porque o embutimento altera o escopo das instruções dentro da UDF.This change in behavior is because inlining changes the scope of statements inside the UDF.

Consulte TambémSee Also

Central de desempenho do Mecanismo de Banco de Dados do SQL Server e do Banco de Dados SQL do Azure Performance Center for SQL Server Database Engine and Azure SQL Database
Guia de arquitetura de processamento de consultas Query Processing Architecture Guide
Referência de operadores físicos e lógicos de plano de execução Showplan Logical and Physical Operators Reference
Junções Joins
Demonstrar o processamento de consulta inteligenteDemonstrating Intelligent Query Processing