Enable parallelism for TSQL scalar UDFs involving CLR function call in SQL Server

Rakesh Kumar 0 Reputation points
2025-05-30T05:25:49.0966667+00:00

We are working on a UDF solution for MSSQL Server. Currently we have scalar TSQL UDFs which calls CLR functions. CLR functions (written in C#) further calls C functions present in a DLL file which is imported by C# layer using DLLImport. Also due to some requirement, our CLR function needs database access therefore we have added following properties to them [SqlFunction(DataAccess = DataAccessKind.Read, SystemDataAccess = SystemDataAccessKind.Read)]

With this design we observe very less performance for the UDFs.

We further investigated and found that when we submit a query involving our UDF, like following
*insert into test_destination(id,name) select id, master.dbo.my_udf1(name) from test_source; (*test_source have 1 million records)

then our UDF is called sequentially one by one for each record i.e., 1 million times. We believe SQL server is not enabling parallelism here for processing the query. Due to this performance is bad.

To enable parallelism for our scalar UDFs, we tried

  • Inlining our UDFs
  • Converting them to inline table valued function
  • Using MAXDOP query hint

but SQL server is not enabling parallelism with these as well.

We did not tried QUERYTRACEON query hint as it is not recommended for production environments.

So is there any way by which we can enable parallelism in SQL server for scalar UDFs which calls a CLR function?

SQL Server Transact-SQL
SQL Server Transact-SQL
SQL Server: A family of Microsoft relational database management and analysis systems for e-commerce, line-of-business, and data warehousing solutions.Transact-SQL: A Microsoft extension to the ANSI SQL language that includes procedural programming, local variables, and various support functions.
197 questions
{count} votes

5 answers

Sort by: Most helpful
  1. Olaf Helper 47,416 Reputation points
    2025-05-30T06:01:50.88+00:00

    then our UDFs is called sequentially one by one for each record i.e., 1 million times. We believe SQL server is not enabling parallelism here for processing the query. Dee to this performance is bad.

    Of course and it doesn't matter if you use a CLR or a plain T-SQL UDF; it's always called per each record; what else do you expect? And that's why it is not a good idea to use a UDF on large data.


  2. Olaf Helper 47,416 Reputation points
    2025-05-30T06:54:17.08+00:00

    Parallelism or not parallelism mainly depends on your base query, not on the UDF. See

    https://learn.microsoft.com/en-us/sql/relational-databases/query-processing-architecture-guide?view=sql-server-ver17


  3. Olaf Helper 47,416 Reputation points
    2025-05-30T12:12:50.2633333+00:00

    I don't know anything abaout your UDF, because you didn't provided an informations abaout.

    May it's possible to re-design the UDF to a TVF = "Table Valued Function", which may perform better.

    See

    https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/linq/how-to-use-table-valued-user-defined-functions

    0 comments No comments

  4. Bruce (SqlWork.com) 77,476 Reputation points Volunteer Moderator
    2025-05-30T15:58:38.3766667+00:00

    SQLServer has many restrictions on insert parallelism.

    • Target table must be a heap (no clustered indexes)
    • tabloc hint required on target table
    • no scalar UDF allowed in query
    • no triggers on target table
    • no indexed views on target table
    • no set rowcount allowed
    • no output clause allowed

    a million row insert should not be too bad, but I suspect that your UDF is creating nested query loop. if the UDF was removed and replaced with sql joins, the optimizer could use a different join option.

    0 comments No comments

  5. Erland Sommarskog 121.3K Reputation points MVP Volunteer Moderator
    2025-05-30T19:48:51.6266667+00:00

    If I understand it correctly, you have a T-SQL function, which calls a CLR function which in its turn can make calls back to the database. I'm wondering if this can be safe to parallelise. (You may know what those callbacks do, but I and SQL Server does not.)

    Insert the data without the UDF. Then set up a Service Broker service with multiple queue readers, and send messages for each partition you divide the data into, so that you have control over the parallelism of the update.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.