关于count(1) 和 count(*)

Q:What is the difference between count(1) and count(*) in a sql query
eg.
select count(1) from emp;
and
select count(*) from emp;

 

A:nothing, they are the same, incur the same amount of work -- do the same thing, take the
same amount of resources.


You can see this via:

ops$tkyte@ORA817.US.ORACLE.COM> alter session set sql_trace=true;

Session altered.

ops$tkyte@ORA817.US.ORACLE.COM> select count(*) from all_objects;

COUNT(*)
----------
27044

ops$tkyte@ORA817.US.ORACLE.COM> select count(1) from all_objects
2 /

COUNT(1)
----------
27044


and the tkprof will show:

 

select count(*)
from
all_objects


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.02 0.02 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 5.56 5.56 0 234998 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 5.58 5.58 0 234998 4 1

select count(1)
from
all_objects


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.02 0.02 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 5.46 5.47 0 234998 4 1
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 5.48 5.49 0 234998 4 1

Same number of blocks read/written/processed, same cpu times (basically) same elapsed
times (basically).

they are identical.


Anyone who thinks different (and I know you are out there) will have to post a test case
like the above or some scientific proof otherwise to be taken seriously....

 

And just before anyone jumps on the "count(primary key) is better" bandwagon, they should take a
look at the example on
http://www.oracledba.co.uk/tips/count_speed.htm
which shows (as Tom points out) that they all work the same nowadays...

 

Hi, tom:

Here is my test result, it show count(*) is much fast than count(1).

In other condition ( for example, a query with join), sometime i can find count(1) is fast than
count(*), but i can't find the sample at present. When i find one, i will send to you.


SVRMGR> connect scott/tiger
Connected.
SVRMGR>
SVRMGR> drop sequence seq_r1000;
Statement processed.
SVRMGR> drop table r1000;
Statement processed.
SVRMGR> create sequence seq_r1000;
Statement processed.
SVRMGR> create table r1000 (id number);
Statement processed.
SVRMGR> insert into r1000 select seq2.nextval from all_objects where rownum<1001
;
1000 rows processed.
SVRMGR> commit;
Statement processed.
SVRMGR> set timing on
Timing ON
SVRMGR> select count(*) from r1000, r1000;
COUNT(*)
----------
1000000
1 row selected.
Parse 0.00 (Elapsed) 0.00 (CPU)
Execute/Fetch 0.43 (Elapsed) 0.00 (CPU)
Total 0.43 0.00
SVRMGR> select count(1) from r1000, r1000;
COUNT(1)
----------
1000000
1 row selected.
Parse 0.00 (Elapsed) 0.00 (CPU)
Execute/Fetch 0.70 (Elapsed) 0.00 (CPU)
Total 0.70 0.00
SVRMGR> select count(*) from r1000, r1000;
COUNT(*)
----------
1000000
1 row selected.
Parse 0.00 (Elapsed) 0.00 (CPU)
Execute/Fetch 0.41 (Elapsed) 0.00 (CPU)
Total 0.41 0.00
SVRMGR> select count(1) from r1000, r1000;
COUNT(1)
----------
1000000
1 row selected.
Parse 0.01 (Elapsed) 0.00 (CPU)
Execute/Fetch 0.69 (Elapsed) 0.00 (CPU)
Total 0.70 0.00
SVRMGR>

Followup August 31, 2001 - 7am UTC:

I'll have to guess, since you don't say, that you are using 7.x and before when count(*) and
count(1) were different (and count(1) was slower). In all releases of the databases for the last
4-5 years, they are the same.

My testing on 8.x with this test case:

drop sequence seq_r1000;
drop table r1000;
create sequence seq_r1000;
create table r1000 (id number);
insert into r1000 select seq_r1000.nextval from all_objects where rownum<1001;

analyze table r1000 compute statistics;
select count(*) from r1000, r1000;
select count(1) from r1000, r1000;


alter session set sql_trace=true;

declare
n number;
begin
for i in 1 .. 10
loop
select count(*) into n from r1000, r1000;
select count(1) into n from r1000, r1000;
end loop;
end;
/


shows:

SELECT COUNT(*)
FROM
R1000,R1000


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 10 0.00 0.00 0 0 0 0
Fetch 10 12.46 12.53 0 40 80 10
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 21 12.46 12.53 0 40 80 10

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 29 (recursive depth: 1)

Rows Row Source Operation
------- ---------------------------------------------------
10 SORT AGGREGATE
10000000 MERGE JOIN CARTESIAN
10010 TABLE ACCESS FULL R1000
10000000 SORT JOIN
10000 TABLE ACCESS FULL R1000

********************************************************************************

SELECT COUNT(1)
FROM
R1000,R1000


call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.01 0 0 0 0
Execute 10 0.00 0.01 0 0 0 0
Fetch 10 12.38 12.38 0 40 80 10
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 21 12.38 12.40 0 40 80 10

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 29 (recursive depth: 1)

Rows Row Source Operation
------- ---------------------------------------------------
10 SORT AGGREGATE
10000000 MERGE JOIN CARTESIAN
10010 TABLE ACCESS FULL R1000
10000000 SORT JOIN
10000 TABLE ACCESS FULL R1000

they are in effect the same...

 

TOM WE ALREADY HAVE LOT'S OF DISCUSSION ABOUNT COUNT(*)
ETC.

LET'S JUST NOT WASTE TIME ANYMORE ON THIS TOPIC

 

I forget to say my database version in last post, it's Oracle 8.1.5 EE on Win NT 4.0.

And I have test it on 8.1.7 just now, the result is:

===========================

C:\>svrmgrl

Oracle Server Manager Release 3.1.7.0.0 - Production

Copyright (c) 1997, 1999, Oracle Corporation. All Rights Reserved.

Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production

SVRMGR> connect scott/tiger
Connected.
SVRMGR> insert into r1000 select seq_r1000.nextval from all_objects where rownum<1001;
1000 rows processed.
SVRMGR> commit;
Statement processed.
SVRMGR> set timing on
Timing ON
SVRMGR> select count(*) from r1000, r1000;
COUNT(*)
----------
4000000
1 row selected.
Parse 0.00 (Elapsed) 0.00 (CPU)
Execute/Fetch 1.33 (Elapsed) 0.00 (CPU)
Total 1.33 0.00
SVRMGR> select count(1) from r1000, r1000;
COUNT(1)
----------
4000000
1 row selected.
Parse 0.02 (Elapsed) 0.00 (CPU)
Execute/Fetch 2.36 (Elapsed) 0.00 (CPU)
Total 2.38 0.00
SVRMGR> select count(*) from r1000, r1000;
COUNT(*)
----------
4000000
1 row selected.
Parse 0.01 (Elapsed) 0.00 (CPU)
Execute/Fetch 1.34 (Elapsed) 0.00 (CPU)
Total 1.35 0.00
SVRMGR> select count(1) from r1000, r1000;
COUNT(1)
----------
4000000
1 row selected.
Parse 0.00 (Elapsed) 0.00 (CPU)
Execute/Fetch 2.33 (Elapsed) 0.00 (CPU)
Total 2.33 0.00
SVRMGR>

============================

If the result is caused by some problem of my environment, what problem is it?

 

Some extra info:

1. There is no need in a separate "count" function as

select sum(1) from emp

does the job (and could do more;).

2. "count" as an abbreviation for sum(1) doesn't really need an argument, for example

select count(1) from emp

and

select count(2) from emp

return the same data.

In short, "count" having an argument is counterintuitive, at least.

 

 

posted @ 2013-12-09 18:17  xcf007  阅读(387)  评论(0编辑  收藏  举报