Parallel plans can be selected with scalar UDF’s

It’s a somewhat known thing that scalar user defined functions can prevent parallel plans from being selected.  There is a catch.  If the scalar function can be inlined, this rule does not apply.  Inlining of scalar functions is available starting in SQL Server 2019 (compatibility level 150).

Demo Query

I will be using the following two demo queries to return a list of CustomerID’s and their respective SalesPerson.  One of the queries calls a version of the UDF which can be inlined.  The other which does not allow inlining.

This query calls a version of the UDF that does not inline:

SELECT dbo.udf_SQLGreaseDemoScalarNotInline(CustomerID) AS SalesPerson, CustomerID
FROM CustomerAccount WITH(NOLOCK) WHERE SalesPerson='BOB'

This can be verified by looking up the udf to see if can be inlined.
SELECT OBJECT_NAME(object_id) AS FunctionName, is_inlineable
FROM sys.sql_modules
WHERE OBJECT_ID = object_id('udf_SQLGreaseDemoScalarNotInline')

As a result, this query cannot be paralleled.

This query calls a version of the UDF that will inline.

SELECT dbo.udf_SQLGreaseDemoScalar(CustomerID) AS SalesPerson, CustomerID
FROM CustomerAccount WITH(NOLOCK) WHERE SalesPerson='BOB'

As a result, the query can be paralleled:

Final thoughts

Parallel plans will not always improve performance (in fact it can hurt in some cases).  But when you are selecting large sets of non-selective data parallel plans can provide major performance improvements.  Happy tuning!