Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is count(*) really expensive?

Tags:

I have a page where I have 4 tabs displaying 4 different reports based off different tables.

I obtain the row count of each table using a select count(*) from <table> query and display number of rows available in each table on the tabs. As a result, each page postback causes 5 count(*) queries to be executed (4 to get counts and 1 for pagination) and 1 query for getting the report content.

Now my question is: are count(*) queries really expensive -- should I keep the row counts (at least those that are displayed on the tab) in the view state of page instead of querying multiple times?

How expensive are COUNT(*) queries ?

like image 550
Anil Namde Avatar asked Apr 27 '10 10:04

Anil Namde


2 Answers

In general, the cost of COUNT(*) cost is proportional to the number of records satisfying the query conditions plus the time required to prepare these records (which depends on the underlying query complexity).

In simple cases where you're dealing with a single table, there are often specific optimisations in place to make such an operation cheap. For example, doing COUNT(*) without WHERE conditions from a single MyISAM table in MySQL - this is instantaneous as it is stored in metadata.

For example, Let's consider two queries:

SELECT  COUNT(*)
FROM    largeTableA a

Since every record satisfies the query, the COUNT(*) cost is proportional to the number of records in the table (i.e., proportional to what it returns) (Assuming it needs to visit the rows and there isnt a specific optimisation in place to handle it)

SELECT  COUNT(*)
FROM    largeTableA a
JOIN    largeTableB b
ON      a.id = b.id

In this case, the engine will most probably use HASH JOIN and the execution plan will be something like this:

  1. Build a hash table on the smaller of the tables
  2. Scan the larger table, looking up each records in a hash table
  3. Count the matches as they go.

In this case, the COUNT(*) overhead (step 3) will be negligible and the query time will be completely defined by steps 1 and 2, that is building the hash table and looking it up. For such a query, the time will be O(a + b): it does not really depend on the number of matches.

However, if there are indexes on both a.id and b.id, the MERGE JOIN may be chosen and the COUNT(*) time will be proportional to the number of matches again, since an index seek will be performed after each match.

like image 103
Quassnoi Avatar answered Nov 18 '22 14:11

Quassnoi


You need to attach SQL Profiler or an app level profiler like L2SProf and look at the real query costs in your context before:

  • guessing what the problem is and trying to determine the likely benefits of a potential solution

  • allowing others to guess for you on da interwebs - there's lots of misinformation without citations about, including in this thread (but not in this post :P)

When you've done that, it'll be clear what the best approach is - i.e., whether the SELECT COUNT is dominating things or not, etc.

And having done that, you'll also know whether any changes you choose to do have had a positive or a negative impact.

like image 32
Ruben Bartelink Avatar answered Nov 18 '22 13:11

Ruben Bartelink