从Count看Oracle执行计划的选择

一、 前言

在调查一个性能问题的时候,一个同事问道,为什么数据库有些时候这么不聪明,明明表上有索引,但是在执行一个简单的count的时候居然全表扫描了!难道不知道走索引更快么?

试图从最简单的count来重新了解oracle查询计划的选择,以及最终产生的结果。虽然有些结果会让人觉得有些意外,并且可能会鄙视,这个查询计划选择真的不够聪明。但稍微用心点的去了解,做的已经足够细致了。大多数情况下,根据我们输入的信息,来自输入的SQL、表结构、索引状况、统计信息,会得出一个比较优的计划。所以和前面一直试图讲到索引和join方式一样,所有这样的选择不是因为数据库厂商这样规定的,而是基于存储的数据的实际情况,就**应该(甚至说不得不)**这么去选择。

 1-- Create table
 2create table IDOUBA.APP_APPLICATIONAUDIT
 3(
 4  ID              NUMBER,
 5  UNIQUEID        NUMBER,
 6  POLICYID        NUMBER,
 7  IP              VARCHAR2(200) not null,
 8  IPNUM           NUMBER not null,
 9  MAC             VARCHAR2(200),
10  USERVISIT       VARCHAR2(100),
11  PHONE           VARCHAR2(200),
12  GROUPNAME       VARCHAR2(100),
13  PORT            NUMBER,
14  APP_URL         VARCHAR2(200),
15  TITLE           VARCHAR2(200),
16  REQUESTS        VARCHAR2(1000),
17  REQIDENTITYCARD VARCHAR2(1000),
18  REQKEY      VARCHAR2(1000),
19  RESPONSEEKEY     VARCHAR2(3000),
20  UPDATETIME      DATE,
21  AUDITTYPE       NUMBER,
22  TITLEID         NUMBER,
23  SUBTITLEID      NUMBER,
24  SERVERIP        VARCHAR2(200),
25  DOMAINNAME      VARCHAR2(200)
26)
27tablespace USERS
28  pctfree 10
29  initrans 1
30  maxtrans 255
31  storage
32  (
33    initial 64K
34    minextents 1
35    maxextents unlimited
36  );
37-- Create/Recreate indexes 
38create index INDEX_UPDATETIME on IDOUBA.APP_APPLICATIONAUDIT (UPDATETIME)
39  tablespace SYSTEM
40  pctfree 10
41  initrans 2
42  maxtrans 255
43  storage
44  (
45    initial 64K
46    minextents 1
47    maxextents unlimited
48  );

表中有20001000条记录,有二十多个字段,包括几个长度比较大的字段。为了实验测试,只是讲IP字段设置为not null。在UpdateTime上建了默认的B树索引。

三、输入

分为三种场景来讨论,然后比较其结果,然后分析该结果。说明数据库的执行计划的选择其实是足够聪明的。

场景一:

  • 表结构:只是在有一个可以为null的列UpdateTime上建了一个索引
  • SQL:最简单的Count。
1select count(*) from IDOUBA.App_ApplicationAudit;      --count(*)
2select count(PolicyId) from IDOUBA.App_ApplicationAudit;      --count(可以null的列)
3select count(IP) from IDOUBA.App_ApplicationAudit;      --count(不可null的列)
4select count(UpdateTime) from IDOUBA.App_ApplicationAudit;  --count(可以为null并且建了索引的列)

场景二:

  • 表结构:和场景一完全相同,只是在有一个可以为null的列UpdateTime上建了一个索引
  • SQL:多了个Where子句,在Where子句中涉及到建了索引的可以为null的列。
1select count(*) from IDOUBA.App_ApplicationAudit where updatetime > to_date('2013-05-01 10:23:44', 'yyyy-mm-dd hh24:mi:ss') ;      --count(*)
2select count(PolicyId) from IDOUBA.App_ApplicationAudit where updatetime > to_date('2013-05-01 10:23:44', 'yyyy-mm-dd hh24:mi:ss') ;    --count(可以null的列)
3select count(IP) from IDOUBA.App_ApplicationAudit where updatetime > to_date('2013-05-01 10:23:44', 'yyyy-mm-dd hh24:mi:ss') ;      --count(不可null的列)
4select count(UpdateTime) from y IDOUBA.App_ApplicationAudit where updatetime > to_date('2013-05-01 10:23:44', 'yyyy-mm-dd hh24:mi:ss') ;  --count(可以为null并且建了索引的列)

场景三:

  • 表结构:除了有一个可以为null的列UpdateTime上建了一个索引外,设置另外一列IpNum列为not null,并且在其上创建索引。
  • SQL:最简单的Count。
1select count(*) from IDOUBA.App_ApplicationAudit;      --count(*)
2select count(PolicyId) from IDOUBA.App_ApplicationAudit;      --count(可以null的列)
3select count(IP) from IDOUBA.App_ApplicationAudit;      --count(不可null的列)
4select count(UpdateTime) from IDOUBA.App_ApplicationAudit;  --count(可以为null并且建了索引的列)

四、实验结果

场景/Count类型 Count(*) Count(PolicyId) 非索引可null的列 Count(IP)非索引not null 的列 Count(Updatetime)可以null的索引列 Count(IPNum) not null 的索引列
执行时间(秒) 物理读 执行操作 执行时间(秒) 物理读 执行操作 执行时间(秒) 物理读 执行操作 执行时间(秒) 物理读 执行操作 执行时间(秒) 物理读 physical reads 执行操作
场景一 50.98 51671 表扫描 47.43 451672 表扫描 47.73 451672 表扫描 8.7 82393 UpdateTime上快速索引扫描
场景二 9.28 82395 UpdateTime上快速索引扫描 48.12 451673 表扫描 9.65 82428 UpdateTime上快速索引扫描 9.03 82394 UpdateTime上快速索引扫描
场景三 5.14 50224 IpNum上快速索引扫描 47.89 451672 表扫描 2.25 15153 IpNum上快速索引扫描 9.06 82393 UpdateTime上快速索引扫描 3.2 82393 IpNum上快速索引扫描

五、结果分析

其实观察查询计划,也就两种,一种快速索引扫描(INDEX FAST FULL SCAN),另外一种是全表扫描(TABLE ACCESS FULL|)。因为实验表中数据量还是不算小,有两千多万,两者的对比还是比较明显。主要体现在总的执行时间,和物理读取上面,差着一个量级。下面对表中的执行结果逐个进行总结和解释。

场景一:

当表中只在一个可以null的列上建索引的情况下。观察到count(*) 、count not null的列count(IP),count 可以null的列PolicyId的count(PolicyId)的效果一样都是走全表扫描(TABLE ACCESS FULL|);而对于count建了索引并且列可以null的列count(UpdateTime),走快速索引扫描(INDEX FAST FULL SCAN)。即只在索引列UpdateTime上, count会走快速索引扫描(INDEX FAST FULL SCAN),其他都是全表扫描。

解释:因为oracle不会索引null,因此扫描该列上的索引只能知道该列上非null的值,而count(*) 和count(非空列)都是统计总行数,从索引上不能获得该信息,只能全表扫描。而count(可空列)就更不能参照该索引了,建了索引的可空列上非null的行数,和在count的可空列上非null的行数没有任何关系,因此也只能全表扫描了。

场景二:

比场景一where子句中包含了可以null的列update的条件where updatetime > to_date(’2013-05-01 10:23:44′, ‘yyyy-mm-dd hh24:mi:ss’) 。观察到count(*)和count not null的列count(IP)和count UpdateTime一样都走updatetime上的快速索引扫描(INDEX FAST FULL SCAN);而count 可null列PolicyId的count(PolicyId)还是全表扫描。

解释:满足类似于pdatetime > to_date(’2013-05-01 10:23:44′, ‘yyyy-mm-dd hh24:mi:ss’)这样可空列上的条件,其实隐含的意思是满足该条件并且该列上取值不为null的行的行数。则在这列上的count,count(*),在其他非null列上的count,表达的都是这个意思,因此可以利用该索引来做索引扫描。而在另外一个可null的列上的count是表示满足该where条件同时在count列上值非null的记录行数,索引列上不为空的行可能在该列上为空,因此不能参照那个索引,只能全表扫描。

场景三:

当表中存在一个not null的列IpNum上建了索引。观察到count(*)和count(IP)在非空索引上快速索引扫描(INDEX FAST FULL SCAN),但是count(ProjectId)还是走原来的全表扫描。即:当表上在一个not null列上建了索引,则只有可Null的列的count走全表扫描,其他的都会走这个建了索引的no null 列的快速索引扫描(INDEX FAST FULL SCAN)。

解释:有一个not null的列上建了索引,则这个索引上的记录数就是表的行数,count(*),count(非空列)都是数行数。但是count(可null 列)是数这个列上不为空的记录数,因此不能参照索引,只能全表扫描了。

六、总结

在Oracle中,Count(Column)是计算Column上不为该列取值不为null的行数,Count一个not null的列其实就是总行数。而Count(*)是不区分null或者not null就是所有记录行数。因此二者语义是一样的,实验也证明了在各种情况下其执行计划总是一样的。对于这两种Count,表上无论哪个索引能提供这样的语义(在例子中场景二和场景三的两个不同索引分别提供了这样的语义),就会走这个索引。如果没有索引能提供这个语义,就不得不走全表扫描了。而Count一个可以为null的列,因为要数本列上到底有多少行的值不为null,因此不能参照别的列,必须在该列上数数,如果该列上有索引,则会在该列的索引上扫描,如果该列上没有索引,则不得不全表扫描。

附:各种场景的执行计划

  1. 只是在有一个可以为null的列UpdateTime上建了一个索引的Count(*)
1SQL> select count(*) from IDOUBA.App_ApplicationAudit;
 1COUNT(*)
 2----------
 3  20001000
 4已用时间:  00: 00: 50.98
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 2649150711
 8-----------------------------------------------------------------------------------
 9| Id  | Operation          | Name                 | Rows  | Cost (%CPU)| Time     |
10-----------------------------------------------------------------------------------
11|   0 | SELECT STATEMENT   |                      |     1 | 99985   (2)| 00:20:00 |
12|   1 |  SORT AGGREGATE    |                      |     1 |            |          |
13|   2 |   TABLE ACCESS FULL| APP_APPLICATIONAUDIT |    19M| 99985   (2)| 00:20:00 |
14-----------------------------------------------------------------------------------
15统计信息
16----------------------------------------------------------
17   166  recursive calls
18      0  db block gets
19 451721  consistent gets
20 451671  physical reads
21      0  redo size
22    410  bytes sent via SQL*Net to client
23    385  bytes received via SQL*Net from client
24      2  SQL*Net roundtrips to/from client
25      5  sorts (memory)
26      0  sorts (disk)
27      1  rows processed
  1. 只是在有一个可以为null的列UpdateTime上建了一个索引的Count一个可以null的列policyId
1SQL> select count(policyId) from IDOUBA.App_ApplicationAudit;
 1COUNT(POLICYID)
 2---------------
 3       20001000
 4已用时间:  00: 00: 47.43
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 2649150711
 8-------------------------------------------------------------------------------------------
 9| Id  | Operation          | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
10-------------------------------------------------------------------------------------------
11|   0 | SELECT STATEMENT   |                      |     1 |     2 |   100K  (2)| 00:20:02 |
12|   1 |  SORT AGGREGATE    |                      |     1 |     2 |            |          |
13|   2 |   TABLE ACCESS FULL| APP_APPLICATIONAUDIT |    19M|    38M|   100K  (2)| 00:20:02 |
14-------------------------------------------------------------------------------------------
15统计信息
16----------------------------------------------------------
17      1  recursive calls
18      0  db block gets
19 451701  consistent gets
20 451672  physical reads
21      0  redo size
22    417  bytes sent via SQL*Net to client
23    385  bytes received via SQL*Net from client
24      2  SQL*Net roundtrips to/from client
25      0  sorts (memory)
26      0  sorts (disk)
27      1	rows processed
  1. 只是在有一个可以为null的列UpdateTime上建了一个索引的Count一个可以null的索引列updatetime:Count(UpdateTime)
1SQL> select count(updatetime) from IDOUBA.App_ApplicationAudit;
 1COUNT(UPDATETIME)
 2-----------------
 3         20001000
 4已用时间:  00: 00: 08.70
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 3909306724
 8------------------------------------------------------------------------------------------
 9| Id  | Operation             | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
10------------------------------------------------------------------------------------------
11|   0 | SELECT STATEMENT      |                  |     1 |     8 | 18204   (3)| 00:03:39 |
12|   1 |  SORT AGGREGATE       |                  |     1 |     8 |            |          |
13|   2 |   INDEX FAST FULL SCAN| INDEX_UPDATETIME |    19M|   152M| 18204   (3)| 00:03:39 |
14------------------------------------------------------------------------------------------
15统计信息
16----------------------------------------------------------
17   164  recursive calls
18      0  db block gets
19  82448  consistent gets
20  82393  physical reads
21      0  redo size
22    419  bytes sent via SQL*Net to client
23    385  bytes received via SQL*Net from client
24      2  SQL*Net roundtrips to/from client
25      5  sorts (memory)
26      0  sorts (disk)
27      1  rows processed
  1. 只是在有一个可以为null的列UpdateTime上建了一个索引的Count一个not null的非索引列IP:Count(IP)
1SQL> select count(Ip) from IDOUBA.App_ApplicationAudit;
 1COUNT(IP)
 2----------
 3  20001000
 4已用时间:  00: 00: 47.73
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 2649150711
 8-----------------------------------------------------------------------------------
 9| Id  | Operation          | Name                 | Rows  | Cost (%CPU)| Time     |
10-----------------------------------------------------------------------------------
11|   0 | SELECT STATEMENT   |                      |     1 | 99985   (2)| 00:20:00 |
12|   1 |  SORT AGGREGATE    |                      |     1 |            |          |
13|   2 |   TABLE ACCESS FULL| APP_APPLICATIONAUDIT |    19M| 99985   (2)| 00:20:00 |
14-----------------------------------------------------------------------------------
15统计信息
16----------------------------------------------------------
17    218  recursive calls
18      0  db block gets
19 451730  consistent gets
20 451672  physical reads
21      0  redo size
22    411  bytes sent via SQL*Net to client
23    385  bytes received via SQL*Net from client
24      2  SQL*Net roundtrips to/from client
25      5  sorts (memory)
26      0  sorts (disk)
27      1	rows processed
  1. 只是在有一个可以为null的列UpdateTime上建了一个索引,Query的Where子句中包含该UpdateTime列的条件where updatetime > to_date(’2013-05-01 10:23:44′, ‘yyyy-mm-dd hh24:mi:ss’) ,Count(*)
1SQL> select count(*) from IDOUBA.App_ApplicationAudit  where updatetime > to_date('2013-05-01 10:23:44', 'yyyy-mm-dd hh24:mi:ss') ;
 1COUNT(*)
 2----------
 3  20001000
 4已用时间:  00: 00: 09.28
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 3909306724
 8------------------------------------------------------------------------------------------
 9| Id  | Operation             | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
10------------------------------------------------------------------------------------------
11|   0 | SELECT STATEMENT      |                  |     1 |     8 | 18373   (4)| 00:03:41 |
12|   1 |  SORT AGGREGATE       |                  |     1 |     8 |            |          |
13|*  2 |   INDEX FAST FULL SCAN| INDEX_UPDATETIME |    19M|   152M| 18373   (4)| 00:03:41 |
14------------------------------------------------------------------------------------------
15Predicate Information (identified by operation id):
16---------------------------------------------------
17   2 - filter("UPDATETIME">TO_DATE('2013-05-01 10:23:44', 'yyyy-mm-dd
18              hh24:mi:ss'))
19统计信息
20----------------------------------------------------------
21    227  recursive calls
22      0  db block gets
23  82464  consistent gets
24  82395  physical reads
25      0  redo size
26    410  bytes sent via SQL*Net to client
27    385  bytes received via SQL*Net from client
28      2  SQL*Net roundtrips to/from client
29      5  sorts (memory)
30      0  sorts (disk)
31      1  rows processed</pre>
  1. 只是在有一个可以为null的列UpdateTime上建了一个索引,Query的Where子句中包含该UpdateTime列的条件where updatetime > to_date(’2013-05-01 10:23:44′, ‘yyyy-mm-dd hh24:mi:ss’) 。Count一个可以null的列PolicyId:Count(PolicyId)
1SQL> select count(policyId) from IDOUBA.App_ApplicationAudit  where updatetime > to_date('2013-05-01 10:23:44', 'yyyy-mm-dd hh24:mi:ss') ;
 1COUNT(POLICYID)
 2---------------
 3       20001000
 4已用时间:  00: 00: 48.12
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 2649150711
 8-------------------------------------------------------------------------------------------
 9| Id  | Operation          | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
10-------------------------------------------------------------------------------------------
11|   0 | SELECT STATEMENT   |                      |     1 |    10 |   101K  (3)| 00:20:20 |
12|   1 |  SORT AGGREGATE    |                      |     1 |    10 |            |          |
13|*  2 |   TABLE ACCESS FULL| APP_APPLICATIONAUDIT |    19M|   190M|   101K  (3)| 00:20:20 |
14-------------------------------------------------------------------------------------------
15Predicate Information (identified by operation id):
16---------------------------------------------------
17   2 - filter("UPDATETIME"&gt;TO_DATE('2013-05-01 10:23:44', 'yyyy-mm-dd hh24:mi:ss'))
18统计信息
19----------------------------------------------------------
20    227  recursive calls
21      0  db block gets
22 451737  consistent gets
23 451673  physical reads
24      0  redo size
25    417  bytes sent via SQL*Net to client
26    385  bytes received via SQL*Net from client
27      2  SQL*Net roundtrips to/from client
28      5  sorts (memory)
29      0  sorts (disk)
30      1  rows processed
  1. 只是在有一个可以为null的列UpdateTime上建了一个索引,Query的Where子句中包含该UpdateTime列的条件where updatetime > to_date(’2013-05-01 10:23:44′, ‘yyyy-mm-dd hh24:mi:ss’) 。Count一个not null的列IP:Count(IP)
1   SQL> select count(ip) from IDOUBA.App_ApplicationAudit  where updatetime > to_date('2013-05-01 10:23:44', 'yyyy-mm-dd hh24:mi:ss') ;
 1COUNT(IP)
 2----------
 3  20001000
 4已用时间:  00: 00: 09.65
 5
 6执行计划
 7----------------------------------------------------------
 8Plan hash value: 3909306724
 9------------------------------------------------------------------------------------------
10| Id  | Operation             | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
11------------------------------------------------------------------------------------------
12|   0 | SELECT STATEMENT      |                  |     1 |     8 | 18373   (4)| 00:03:41 |
13|   1 |  SORT AGGREGATE       |                  |     1 |     8 |            |          |
14|*  2 |   INDEX FAST FULL SCAN| INDEX_UPDATETIME |    19M|   152M| 18373   (4)| 00:03:41 |
15------------------------------------------------------------------------------------------
16Predicate Information (identified by operation id):
17---------------------------------------------------
18   2 - filter("UPDATETIME"&gt;TO_DATE('2013-05-01 10:23:44', 'yyyy-mm-dd hh24:mi:ss'))
19统计信息
20----------------------------------------------------------
21      1  recursive calls
22      0  db block gets
23  82428  consistent gets
24  82393  physical reads
25      0  redo size
26    411  bytes sent via SQL*Net to client
27    385  bytes received via SQL*Net from client
28      2  SQL*Net roundtrips to/from client
29      0  sorts (memory)
30      0  sorts (disk)
31      1  rows processed
  1. 只是在有一个可以为null的列UpdateTime上建了一个索引,Query的Where子句中包含该UpdateTime列的条件where updatetime > to_date(’2013-05-01 10:23:44′, ‘yyyy-mm-dd hh24:mi:ss’) 。Count该可以 null的索引列UpdateTime:Count(UpdateTime)
1SQL> select count(updatetime) from IDOUBA.App_ApplicationAudit where updatetime > to_date('2013-05-01 10:23:44', 'yyyy-mm-dd hh24:mi:ss') ;
 1COUNT(UPDATETIME)
 2-----------------
 3         20001000
 4已用时间:  00: 00: 09.03
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 3909306724
 8------------------------------------------------------------------------------------------
 9| Id  | Operation             | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
10------------------------------------------------------------------------------------------
11|   0 | SELECT STATEMENT      |                  |     1 |     8 | 18204   (3)| 00:03:39 |
12|   1 |  SORT AGGREGATE       |                  |     1 |     8 |            |          |
13|   2 |   INDEX FAST FULL SCAN| INDEX_UPDATETIME |    19M|   152M| 18204   (3)| 00:03:39 |
14------------------------------------------------------------------------------------------
15统计信息
16----------------------------------------------------------
17    185  recursive calls
18      0  db block gets
19  82460  consistent gets
20  82394  physical reads
21      0  redo size
22    419  bytes sent via SQL*Net to client
23    385  bytes received via SQL*Net from client
24      2  SQL*Net roundtrips to/from client
25      5  sorts (memory)
26      0  sorts (disk)
27      1  rows processed
  1. 在一个not null的列IPNum创建索引count(*)
1SQL> select count(*) from IDOUBA.App_ApplicationAudit;
 1COUNT(*)
 2----------
 3  20001000
 4已用时间:  00: 00: 05.14
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 2581539037
 8-----------------------------------------------------------------------------
 9| Id  | Operation             | Name        | Rows  | Cost (%CPU)| Time     |
10-----------------------------------------------------------------------------
11|   0 | SELECT STATEMENT      |             |     1 | 11435   (5)| 00:02:18 |
12|   1 |  SORT AGGREGATE       |             |     1 |            |          |
13|   2 |   INDEX FAST FULL SCAN| INDEX_IPNUM |    19M| 11435   (5)| 00:02:18 |
14-----------------------------------------------------------------------------
15统计信息
16----------------------------------------------------------
17      1  recursive calls
18      0  db block gets
19  50253  consistent gets
20  50224  physical reads
21      0  redo size
22    410  bytes sent via SQL*Net to client
23    385  bytes received via SQL*Net from client
24      2  SQL*Net roundtrips to/from client
25      0  sorts (memory)
26      0  sorts (disk)
27      1	rows processed

10 在一个not null的列IPNum创建索引。Count可null的列PolicyId:Count(PolicyId)

1SQL> select count(policyId) from IDOUBA.App_ApplicationAudit;
 1COUNT(POLICYID)
 2---------------
 3       20001000
 4已用时间:  00: 00: 47.89
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 2649150711
 8-------------------------------------------------------------------------------------------
 9| Id  | Operation          | Name                 | Rows  | Bytes | Cost (%CPU)| Time     |
10-------------------------------------------------------------------------------------------
11|   0 | SELECT STATEMENT   |                      |     1 |     2 |   100K  (2)| 00:20:02 |
12|   1 |  SORT AGGREGATE    |                      |     1 |     2 |            |          |
13|   2 |   TABLE ACCESS FULL| APP_APPLICATIONAUDIT |    19M|    38M|   100K  (2)| 00:20:02 |
14-------------------------------------------------------------------------------------------
15统计信息
16----------------------------------------------------------
17      1  recursive calls
18      0  db block gets
19 451701  consistent gets
20 451672  physical reads
21      0  redo size
22    417  bytes sent via SQL*Net to client
23    385  bytes received via SQL*Net from client
24      2  SQL*Net roundtrips to/from client
25      0  sorts (memory)
26      0  sorts (disk)
27      1	rows processed

11 在一个not null的列IPNum创建索引。Count not null的列IP:Count(IP)

1SQL> select count(Ip) from IDOUBA.App_ApplicationAudit;
 1COUNT(IP)
 2----------
 3  20001000
 4已用时间:  00: 00: 02.25
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 2581539037
 8-----------------------------------------------------------------------------
 9| Id  | Operation             | Name        | Rows  | Cost (%CPU)| Time     |
10-----------------------------------------------------------------------------
11|   0 | SELECT STATEMENT      |             |     1 | 11435   (5)| 00:02:18 |
12|   1 |  SORT AGGREGATE       |             |     1 |            |          |
13|   2 |   INDEX FAST FULL SCAN| INDEX_IPNUM |    19M| 11435   (5)| 00:02:18 |
14-----------------------------------------------------------------------------
15统计信息
16----------------------------------------------------------
17    196  recursive calls
18      0  db block gets
19  50290  consistent gets
20  15153  physical reads
21      0  redo size
22    411  bytes sent via SQL*Net to client
23    385  bytes received via SQL*Net from client
24      2  SQL*Net roundtrips to/from client
25      5  sorts (memory)
26      0  sorts (disk)
27      1	rows processed

12 在一个not null的列IPNum创建索引。Count另外一个建了索引的可null的列UpdateTime:Count(UpdateTime)

1SQL> select count(updatetime) from IDOUBA.App_ApplicationAudit;
 1COUNT(UPDATETIME)
 2-----------------
 3         20001000
 4已用时间:  00: 00: 09.06
 5执行计划
 6----------------------------------------------------------
 7Plan hash value: 3909306724
 8------------------------------------------------------------------------------------------
 9| Id  | Operation             | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
10------------------------------------------------------------------------------------------
11|   0 | SELECT STATEMENT      |                  |     1 |     8 | 18204   (3)| 00:03:39 |
12|   1 |  SORT AGGREGATE       |                  |     1 |     8 |            |          |
13|   2 |   INDEX FAST FULL SCAN| INDEX_UPDATETIME |    19M|   152M| 18204   (3)| 00:03:39 |
14------------------------------------------------------------------------------------------
15统计信息
16----------------------------------------------------------
17      1  recursive calls
18      0  db block gets
19  82428  consistent gets
20  82393  physical reads
21      0  redo size
22    419  bytes sent via SQL*Net to client
23    385  bytes received via SQL*Net from client
24      2  SQL*Net roundtrips to/from client
25      0  sorts (memory)
26      0  sorts (disk)
27      1	rows processed

完。