Is COUNT(DISTINCT PRIMARY_KEY) faster than COUNT(*)

countoracle

I haven't got a particular problem here, I'm just interested. One of my associates uses COUNT(DISTINCT(PRIMARY_KEY)) every time he needs to select all the data from a table (with 100m + rows) is it any quicker to do it this way rather than just count(*)? If it's the primary key surely the database knows that it's just pulling a count for the whole database and why?

Best Answer

It is slower.

SQL> select count(*) from t1;

  COUNT(*)
----------
   4023040

SQL> alter table t1 add primary key (object_id);

Table altered.

SQL> select count(*) from t1;

  COUNT(*)
----------
   4023040

-----------------------------------------------------------------------------------------------
| Id  | Operation             | Name        | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |             |      1 |        |      1 |00:00:00.54 |    8852 |
|   1 |  SORT AGGREGATE       |             |      1 |      1 |      1 |00:00:00.54 |    8852 |
|   2 |   INDEX FAST FULL SCAN| SYS_C004079 |      1 |   3766K|   4023K|00:00:00.35 |    8852 |
-----------------------------------------------------------------------------------------------

Plain count(*) finished in 0.54 seconds.

SQL> select count(distinct object_id) from t1;

COUNT(DISTINCT(OBJECT_ID))
--------------------------
                   4023040

--------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation               | Name        | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  | Writes |  OMem |  1Mem | Used-Mem | Used-Tmp|
--------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |             |      1 |        |      1 |00:00:05.22 |    8852 |   6944 |   6944 |       |       |          |         |
|   1 |  SORT AGGREGATE         |             |      1 |      1 |      1 |00:00:05.22 |    8852 |   6944 |   6944 |       |       |          |         |
|   2 |   VIEW                  | VW_DAG_0    |      1 |   3766K|   4023K|00:00:04.96 |    8852 |   6944 |   6944 |       |       |          |         |
|   3 |    HASH GROUP BY        |             |      1 |   3766K|   4023K|00:00:04.47 |    8852 |   6944 |   6944 |   178M|    21M|   32M (1)|   57344 |
|   4 |     INDEX FAST FULL SCAN| SYS_C004079 |      1 |   3766K|   4023K|00:00:00.41 |    8852 |      0 |      0 |       |       |          |         |
--------------------------------------------------------------------------------------------------------------------------------------------------------

5.22 seconds, and it used 32 MB memory, and even had to use temp, because it has to GROUP BY because of DISTINCT.