Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

select count(*) vs keep a counter

Assuming indexes are put in place, and absolute-count-accuracy is not necessary (it's okay to be off by one or two), is it okay to use:

Option A

select count(*) 
  from Table 
 where Property = @Property

vs

Option B

update PropertyCounters
   SET PropertyCount = PropertyCount + 1  
 where Property = @Property

then doing:

select PropertyCount 
  from PropertyCounters 
 where Property = @Property

How much performance degradation can I reasonably expect from doing select count(*) as the table grows into thousands/millions of records?

like image 527
Lou Avatar asked Aug 17 '10 01:08

Lou


People also ask

What is the difference between select * and select COUNT (*)?

Select * Would return the entire table while Select Count(*) would return the number of rows.

Are COUNT (*) and COUNT () the same function?

As you've already learned, COUNT(*) will count all the rows in the table, including NULL values. On the other hand, COUNT(column name) will count all the rows in the specified column while excluding NULL values.

Which is better COUNT (*) or COUNT 1?

There is no difference. "1" is a non-null expression: so it's the same as COUNT(*) .

What does select COUNT (*) mean?

COUNT(*) does not require an expression parameter because by definition, it does not use information about any particular column. COUNT(*) returns the number of rows in a specified table, and it preserves duplicate rows. It counts each row separately. This includes rows that contain null values.


2 Answers

Keeping a separate count column in addition to the real data is a denormalisation. There are reasons why you might need to do it for performance, but you shouldn't go there until you really need to. It makes your code more complicated, with more chance of inconsistencies creeping in.

For the simple case where the query really is just SELECT COUNT(property) FROM table WHERE property=..., there's no reason to denormalise; you can make that fast by adding an index on the property column.

like image 166
bobince Avatar answered Sep 30 '22 13:09

bobince


You didn't specify the platform, but since you use T-SQL syntax for @variables I'll venture a SQL Server platform specific answer:

count(*), or strictly speaking would be count_big(*), is an expression that can be used in indexed views, see Designing Indexed Views.

create view vwCounts
with schembinding
as select Property, count_big(*) as Count
from dbo.Table
group by Property;

create unique clustered index cdxCounts on vwCounts(Property);

select Count 
from vwCount with (noexpand)
where Property = @property;

On Enterprise Edition the optimizer will even use the indexed view for your original query:

select count_big(*)
from Table
where Property = @property;

So in the end you get your cake and eat it too: the property is already aggregated and maintained for your for free by the engine. The price is that updates have to maintain the indexed view (they will not recompute the aggregate count though) and the aggregation will create hot spots for contention (locks on separate rows on Table will contend for same count(*) update on the indexed view).

like image 28
Remus Rusanu Avatar answered Sep 30 '22 14:09

Remus Rusanu