count(*), count(1) ,count(唯一键索引),count(非唯一键索引),count(存在null索引)的效率

看见pub上面有人问count(*),count(1),count(索引字段)有什么区别,效率是否相同,恩 是个好问题下面我来研究研究

SQL> create table test as select * from dba_objects;

表已创建。

SQL> alter table test modify object_id primary key;

表已更改。

SQL> set autot trace
SQL> alter system flush buffer_cache;

系统已更改。

SQL> alter system flush shared_pool;

系统已更改。

SQL> select count(1) from test;
执行计划
----------------------------------------------------------
Plan hash value: 33512955

-----------------------------------------------------------------------------
| Id  | Operation             | Name        | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |             |     1 |    25   (4)| 00:00:01 |
|   1 |  SORT AGGREGATE       |             |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| SYS_C005230 | 56783 |    25   (4)| 00:00:01 |
-----------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
        326  recursive calls
          0  db block gets
        236  consistent gets
        620  physical reads
          0  redo size
        414  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          5  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> alter system flush buffer_cache;

系统已更改。

SQL> alter system flush shared_pool;

系统已更改。

SQL> select count(*) from test;
执行计划
----------------------------------------------------------
Plan hash value: 33512955

-----------------------------------------------------------------------------
| Id  | Operation             | Name        | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |             |     1 |    25   (4)| 00:00:01 |
|   1 |  SORT AGGREGATE       |             |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| SYS_C005230 | 56783 |    25   (4)| 00:00:01 |
-----------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
       1112  recursive calls
          0  db block gets
        353  consistent gets
        632  physical reads
          0  redo size
        414  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         12  sorts (memory)
          0  sorts (disk)
          1  rows processed

上面的测试清空了缓存,现在不清空缓存

SQL> select count(1) from test;
执行计划
----------------------------------------------------------
Plan hash value: 33512955

-----------------------------------------------------------------------------
| Id  | Operation             | Name        | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |             |     1 |    25   (4)| 00:00:01 |
|   1 |  SORT AGGREGATE       |             |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| SYS_C005230 | 56783 |    25   (4)| 00:00:01 |
-----------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        110  consistent gets
          0  physical reads
          0  redo size
        414  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> select count(*) from test;
执行计划
----------------------------------------------------------
Plan hash value: 33512955

-----------------------------------------------------------------------------
| Id  | Operation             | Name        | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |             |     1 |    25   (4)| 00:00:01 |
|   1 |  SORT AGGREGATE       |             |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| SYS_C005230 | 56783 |    25   (4)| 00:00:01 |
-----------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        110  consistent gets
          0  physical reads
          0  redo size
        414  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

现在将表的主键去掉

SQL> alter table test drop  primary key ;

表已更改。

SQL> alter system flush shared_pool;

系统已更改。

SQL> alter system flush buffer_cache;

系统已更改。

SQL> select count(*) from test;
执行计划
----------------------------------------------------------
Plan hash value: 1950795681

-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   140   (2)| 00:00:02 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TEST | 56783 |   140   (2)| 00:00:02 |
-------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
        274  recursive calls
          0  db block gets
        795  consistent gets
        699  physical reads
          0  redo size
        414  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          4  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> alter system flush shared_pool;

系统已更改。

SQL> alter system flush buffer_cache;

系统已更改。

SQL> select count(1) from test;
执行计划
----------------------------------------------------------
Plan hash value: 1950795681

-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   140   (2)| 00:00:02 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TEST | 56783 |   140   (2)| 00:00:02 |
-------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
        282  recursive calls
          0  db block gets
        797  consistent gets
        701  physical reads
          0  redo size
        414  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          4  sorts (memory)
          0  sorts (disk)
          1  rows processed

现在不刷新缓存,多运行几次

SQL> select count(*) from test;
执行计划
----------------------------------------------------------
Plan hash value: 1950795681

-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   140   (2)| 00:00:02 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TEST | 56783 |   140   (2)| 00:00:02 |
-------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement

统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        691  consistent gets
          0  physical reads
          0  redo size
        414  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> select count(1) from test;
执行计划
----------------------------------------------------------
Plan hash value: 1950795681

-------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Cost (%CPU)| Time     |
-------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   140   (2)| 00:00:02 |
|   1 |  SORT AGGREGATE    |      |     1 |            |          |
|   2 |   TABLE ACCESS FULL| TEST | 56783 |   140   (2)| 00:00:02 |
-------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement


统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        691  consistent gets
          0  physical reads
          0  redo size
        414  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
存在主键的时候,从统计信息上看,第一次硬解析的时候count(1)效率比count(*)高一点点,但是一旦硬解析之后,再次执行他们的效率是相同的,在没有主键的时候,从统计信息上看,第一次硬解析的时候count(*)的效率比count(1)高点点,再次执行的时候,他们的效率是相同的。由此可以说count(*),count(1)他们的效率是相同的。

现在来测试一下count(索引字段),这个时候分两种情况

1.该字段中有null

2.该字段无null

 

 

第一种情况(该字段有null):

SQL> update test set object_name=null where owner='SCOTT';

已更新13行。

SQL> commit;

提交完成。

SQL> create index ind_on on test(object_name);

索引已创建。

SQL> select count(*) from test;

  COUNT(*)
----------
     49916

SQL> alter system flush buffer_cache;

系统已更改。

SQL> alter system flush shared_pool;

系统已更改。

SQL> select count(object_name) from test;

COUNT(OBJECT_NAME)
------------------
             49903
执行计划
----------------------------------------------------------
Plan hash value: 1496018862

--------------------------------------------------------------------------------
| Id  | Operation             | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |     1 |    66 |    53   (2)| 00:00:01 |
|   1 |  SORT AGGREGATE       |        |     1 |    66 |            |          |
|   2 |   INDEX FAST FULL SCAN| IND_ON | 56783 |  3659K|    53   (2)| 00:00:01 |
--------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
        990  recursive calls
          0  db block gets
        472  consistent gets
        766  physical reads
          0  redo size
        424  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         10  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> select count(object_name) from test;

COUNT(OBJECT_NAME)
------------------
             49903
执行计划
----------------------------------------------------------
Plan hash value: 1496018862

--------------------------------------------------------------------------------
| Id  | Operation             | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |     1 |    66 |    53   (2)| 00:00:01 |
|   1 |  SORT AGGREGATE       |        |     1 |    66 |            |          |
|   2 |   INDEX FAST FULL SCAN| IND_ON | 56783 |  3659K|    53   (2)| 00:00:01 |
--------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        253  consistent gets
          0  physical reads
          0  redo size
        424  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

第二种情况(该字段无null值)

SQL> update test set object_name='DEPT' where owner='SCOTT';

已更新13行。

SQL> commit;

提交完成。

SQL> alter system flush buffer_cache;

系统已更改。

SQL> alter system flush shared_pool;

系统已更改。

SQL> select count(object_name) from test;

COUNT(OBJECT_NAME)
------------------
             49916
执行计划
----------------------------------------------------------
Plan hash value: 1496018862

--------------------------------------------------------------------------------
| Id  | Operation             | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |     1 |    66 |    53   (2)| 00:00:01 |
|   1 |  SORT AGGREGATE       |        |     1 |    66 |            |          |
|   2 |   INDEX FAST FULL SCAN| IND_ON | 56783 |  3659K|    53   (2)| 00:00:01 |
--------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
        990  recursive calls
          0  db block gets
        472  consistent gets
        759  physical reads
          0  redo size
        424  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         10  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> select count(object_name) from test;

COUNT(OBJECT_NAME)
------------------
             49916
执行计划
----------------------------------------------------------
Plan hash value: 1496018862

--------------------------------------------------------------------------------
| Id  | Operation             | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |        |     1 |    66 |    53   (2)| 00:00:01 |
|   1 |  SORT AGGREGATE       |        |     1 |    66 |            |          |
|   2 |   INDEX FAST FULL SCAN| IND_ON | 56783 |  3659K|    53   (2)| 00:00:01 |
--------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        253  consistent gets
          0  physical reads
          0  redo size
        424  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

在硬解析的时候,从统计信息上看,有null值时count(索引字段)的花费要比没有null值时高,而软解析的时候他们的效率是一样的。另外需要注意的就是count(索引字段),存在null值的时候,count不会统计null值,因为ORACLE不会对索引列上包含null值的行进行索引,这点需要特别注意。

下面比较count(唯一键索引)与非唯一键索引的效率

SQL> create unique index ind_oid on test(object_id);

索引已创建。

SQL> set autot on
SQL> select count(object_id) from test;

COUNT(OBJECT_ID)
----------------
           49916
执行计划
----------------------------------------------------------
Plan hash value: 886325522

---------------------------------------------------------------------------------
| Id  | Operation             | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |         |     1 |    13 |    25   (4)| 00:00:01 |
|   1 |  SORT AGGREGATE       |         |     1 |    13 |            |          |
|   2 |   INDEX FAST FULL SCAN| IND_OID | 56783 |   720K|    25   (4)| 00:00:01 |
---------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
          5  recursive calls
          0  db block gets
        187  consistent gets
        109  physical reads
          0  redo size
        422  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

SQL> drop index ind_oid;

索引已删除。

SQL> create index ind_oid on test(object_id);

索引已创建。

SQL> select count(object_id) from test;

COUNT(OBJECT_ID)
----------------
           49916
执行计划
----------------------------------------------------------
Plan hash value: 886325522

---------------------------------------------------------------------------------
| Id  | Operation             | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |         |     1 |    13 |    26   (4)| 00:00:01 |
|   1 |  SORT AGGREGATE       |         |     1 |    13 |            |          |
|   2 |   INDEX FAST FULL SCAN| IND_OID | 56783 |   720K|    26   (4)| 00:00:01 |
---------------------------------------------------------------------------------

Note
-----
   - dynamic sampling used for this statement
统计信息
----------------------------------------------------------
         36  recursive calls
          0  db block gets
        197  consistent gets
        110  physical reads
          0  redo size
        422  bytes sent via SQL*Net to client
        400  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

 

由此可见count(唯一键索引的效率)比count(非唯一键)效率高。

 

总结:

当表存在主键或者唯一索引的时候count(*),count(1)效率相同。count(唯一键索引字段)比count(非唯一键索引字段)效率高。

count(非唯一键索引,列存在null)与count(非唯一键索引,列不存在null)的效率差不多,不过count(唯一键索引,列存在null)的值比count(*)小,因为null的值不会被记录在索引中。

注意:我这里所指的效率主要是指的cost,经过多次执行后的cost。

 

 

 

posted on 2009-12-11 13:01  如果蜗牛有爱情  阅读(219)  评论(0编辑  收藏  举报

导航