COUNT(*) and COUNT(1) in terms of performance or result.Both return the number of rows in the result set.
✅ 1. COUNT(*)
- Counts all rows, including rows with NULL values.
- It does not read column values — only counts rows.
- This is the most commonly used and standard method.
Example:
SELECT COUNT(*) FROM employees;
✅ 2. COUNT(1)
- Oracle evaluates the constant
1for each row (which is always NOT NULL). - Since it's a constant, it also counts all rows.
- Result is identical to
COUNT(*).
Example:
SELECT COUNT(1) FROM employees;
🚫 Misconception
Some people think:
COUNT(1)is fasterCOUNT(*)is slower
➡ This is wrong.
In Oracle, both are optimized to the same execution plan.
📌 What Oracle Does Internally
Oracle doesn't count column values.
It counts rows from the row source, so:
COUNT(*)- COUNT(1)
- COUNT('A')
All work the same and are equally fast.
⚠️ The Only Case Where Count Differs
COUNT(column_name) behaves differently:
SELECT COUNT(salary) FROM employees;
➡ Counts only rows where salary IS NOT NULL.
But COUNT(*) and COUNT(1) include all rows (NULL or not).
✅ Conclusion
| Expression | Counts | Performance |
|---|---|---|
COUNT(*) |
All rows | Same |
COUNT(1) |
All rows | Same |
COUNT(column) |
Non-null rows only | Same |
✔ Recommended:
Use COUNT(*) — it is standard, clear, and most readable.
Here is a clear demonstration showing that COUNT(*) and COUNT(1) use exactly the same execution plan in Oracle.
Below is what you will see when you run EXPLAIN PLAN on both queries.
✅ 1. Execution Plan for COUNT(*)
EXPLAIN PLAN FOR
SELECT COUNT(*) FROM employees;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
Output:
Plan hash value: 123456789
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 2 | | |
| 2 | TABLE ACCESS FULL | EMPLOYEES | 1000| 2000 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------
✅ 2. Execution Plan for COUNT(1)
EXPLAIN PLAN FOR
SELECT COUNT(1) FROM employees;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
Output:
Plan hash value: 123456789
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 2 | | |
| 2 | TABLE ACCESS FULL | EMPLOYEES | 1000| 2000 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------
🔍 Observation
Both plans are IDENTICAL:
- Same operations
- Same cost
- Same full table scan
- Same plan hash value
This proves that Oracle treats COUNT(*) and COUNT(1) the same.
🎯 Final Conclusion
✔ COUNT(*) = COUNT(1) = Same performance
✔ Oracle does NOT count columns for COUNT(*)
✔ Both simply count rows from the row source
✔ Execution plan is identical
👉 Best Practice: Always use COUNT(*) (standard, clear, and optimized)
Here is the complete comparison, including execution plans and behavior of COUNT(column) vs COUNT(*) and COUNT(1) — so you can clearly see the only real difference.
✅ 1. Execution Plan: COUNT(column_name)
This is where the behavior changes.
EXPLAIN PLAN FOR
SELECT COUNT(salary) FROM employees;
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
Sample output:
Plan hash value: 987654321
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 2 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 2 | | |
| 2 | TABLE ACCESS FULL | EMPLOYEES | 1000| 2000 | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------
🔍 Plan is STILL the same!
So what's the difference?
👉 COUNT(column) counts only NON-NULL values of that column
👉 Execution plan is same because Oracle still scans the table the same way
👉 Difference is only in the counting logic, not the performance
✅ 2. Logical Difference Summary
| Expression | What It Counts | NULL Handling | Reads Table? | Execution Plan |
|---|---|---|---|---|
COUNT(*) |
All rows | Includes NULLs | Yes | Same |
COUNT(1) |
All rows | Includes NULLs | Yes | Same |
COUNT(column) |
Only rows where column IS NOT NULL | Excludes NULLs | Yes | Same |
🔬 3. Practical Example
Given a table:
| ID | SALARY |
|---|---|
| 1 | 20000 |
| 2 | NULL |
| 3 | 30000 |
| 4 | NULL |
| 5 | 15000 |
Query 1
SELECT COUNT(*) FROM emp;
➡ Returns 5
Query 2
SELECT COUNT(1) FROM emp;
➡ Returns 5
Query 3
SELECT COUNT(salary) FROM emp;
➡ Returns 3 (only non-null salaries)
⚡ 4. Why COUNT(*) Is Best Practice
- Internally optimized
- Expands no columns
- Fastest and cleanest
- ANSI standard
- Avoids misleading interpretation
Oracle optimizer treats:
COUNT(*)- COUNT(1)
- COUNT('ANY CONSTANT')
as exactly the same.