Tuesday, March 16, 2021

Index use - COUNT(*) vs COUNT(1)

The question whether to use COUNT(*) or COUNT(1) has been doing the rounds on the internet again, the question this time is whether or not COUNT(*) forces the optimiser to scan all rows or not.

I'm going to query Sales.Orders table of the WideWorldImporters sample database and use a where clause that should take advantage of a non-clustered index on CustomerID. 

Firstly I'll run a select on everything and I can see the following query returns 107 rows:

SELECT *
FROM [WideWorldImporters].[Sales].[Orders]
WHERE CustomerID = 832

Now lets try replacing the select everything with count(1) and this time I will include the actual execution plan.

SELECT COUNT(1)
FROM [WideWorldImporters].[Sales].[Orders]
WHERE CustomerID = 832


The execution plan using COUNT(1) has used a seek on the Index and we can see from the operator properties that only 107 rows were read:



Now I'll try a COUNT(*) and I have added a OPTION (RECOMPILE) hint to ensure a brand new execution plan is used:

SELECT COUNT(*)
FROM [WideWorldImporters].[Sales].[Orders]
WHERE CustomerID = 832
OPTION (RECOMPILE)

The execution plan is identical, even though we're using COUNT(*) the optimiser can still seek on the relevant index for the where clause in the query:


Just to double check; our index seek operator has the same number of rows read as well:


In terms of what index can be used COUNT(*) and COUNT(1) are identical and both will use an index seek if the optimiser deems it the most efficient method and COUNT(*) definitely does not force a scan.

No comments:

Post a Comment

Breaking up with SQL Server

I was inspired to write this after reading a post from Dave Mason regarding breaking up with Big Tech companies. Yet again I haven't wr...