Question

Azure SQL Database - Standard Edition (S3 Service Tier)

Why does Batch Mode only come into effect when using Aggregate Functions?

DROP TABLE IF EXISTS dbo.TransCS

CREATE TABLE dbo.TransCS (
     Col1 INT 
    ,Col2 AS Col1*2
)
CREATE CLUSTERED COLUMNSTORE INDEX CS_TransCS on dbo.TransCS;

WITH
    L0   AS(SELECT 1 AS c UNION ALL SELECT 1),
    L1   AS(SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
    L2   AS(SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
    L3   AS(SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
    L4   AS(SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
    L5   AS(SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
    Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) 
    AS n FROM L5)
INSERT INTO dbo.TransCS (Col1)
SELECT TOP (1000000) n FROM Nums ORDER BY n; 

Insert 1 Million rows

Row Processing

SELECT * FROM dbo.TransCS

Execution Plan

Batch Processing

SELECT Col1, Col2, SUM(Col2)OVER ()
FROM dbo.TransCS

Execution Plan

Is there a way to utilise the performance benefits without using Agg functions? Documentation on this is thin.

Was it helpful?

Solution

Background

Back in July 2017, Niko blogged about a change in SQL Server 2017

...in SQL Server 2017 there is an internal optimisation for the Query Optimiser, that shall apply FULL optimisation to the execution plans with the Columnstore Indexes, avoiding the pitfall of executing them in the Row Execution Mode

Prior to that, you would get row-mode execution for "trivial plans," even when there were columnstore objects involved.

The execution plan you shared shows that the first query has this problem, which you can confirm in the XML:

StatementOptmLevel="TRIVIAL" 

Workaround

One way to work around this, get FULL optimization, and thus get a batch mode scan, is to add a subquery that won't affect your results, like this:

SELECT * FROM dbo.TransCS WHERE (SELECT 1) = 1;

The second query gets full optimization already because of the aggregate function.

Why is this happening?

The only things that come to mind for why this might happen are:

  • your database has a compatability level of 130 or lower (this seems unlikely because I can see in the execution plan that the 140 cardinality estimator is being used)
  • this is a change / regression in Azure SQL Database specifically
    • The "build" indicated in the execution plan is 15.0.1100.504, which looks like a SQL Server 2019 build number (which makes sense, since this is Azure). I don't have a 2019 instance to test on, but the change in behavior might be there as well

You may want to report this to Microsoft on the feedback site.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top