看效率最最好以查询计划为主,上面两个语句如果仅是统计表的行数,大多数情况下效率是一样的 SQL> select count(*) from emp; COUNT(*) ---------- 14 执行计划 ---------------------------------------------------------- Plan hash value: 2937609675------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 1 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FULL SCAN| PK_EMP | 14 | 1 (0)| 00:00:01 | -------------------------------------------------------------------SQL> select count(empno) from emp;COUNT(EMPNO) ------------ 14 执行计划 ---------------------------------------------------------- Plan hash value: 2937609675------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 1 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FULL SCAN| PK_EMP | 14 | 1 (0)| 00:00:01 | -------------------------------------------------------------------
1)count(*) 优化器会判断是否可以走索引的,如果含有主键或非空索引,那么计划就会走索引 2)如果ID列不是通常的B索引,或者该列就没有索引,那么count(ID)为统计非空和空的行总数 SQL> select count(*) from 2 (select null from dual union all 3 select 1 from dual) t; COUNT(*) ---------- 2
1)count(*) 优化器会判断是否可以走索引的,如果含有主键或非空索引,那么计划就会走索引 2)如果ID列不是通常的B索引,或者该列就没有索引,那么count(ID)为统计非空和空的行总数 SQL> select count(*) from 2 (select null from dual union all 3 select 1 from dual) t; COUNT(*) ---------- 21)count(*) 优化器会判断是否可以走索引的是的、会判断、CBO会对所有可能的路线都进行判断、然后选择其中成本最低的那条去走、如果含有主键或非空索引,那么计划就会走索引你所认为的含主键走索引、也是把索引当"瘦表"来回答一个查询、至于"非空索引"这个我有点不太理解?非空?b树索引不能存空值吧2)count(ID)为统计非空和空的行总数即便不存在索引、你都认为count(id)统计总行数吗?如果是这样、我不是很赞同、
1)count(*) 优化器会判断是否可以走索引的,如果含有主键或非空索引,那么计划就会走索引 2)如果ID列不是通常的B索引,或者该列就没有索引,那么count(ID)为统计非空和空的行总数 SQL> select count(*) from 2 (select null from dual union all 3 select 1 from dual) t; COUNT(*) ---------- 21)count(*) 优化器会判断是否可以走索引的是的、会判断、CBO会对所有可能的路线都进行判断、然后选择其中成本最低的那条去走、如果含有主键或非空索引,那么计划就会走索引你所认为的含主键走索引、也是把索引当"瘦表"来回答一个查询、至于"非空索引"这个我有点不太理解?非空?b树索引不能存空值吧2)count(ID)为统计非空和空的行总数即便不存在索引、你都认为count(id)统计总行数吗?如果是这样、我不是很赞同、 1) "非空索引” 我说的可能不太清楚,我指的是 非空约束的索引列 SQL> create table t(id int not null,nn varchar2(50));表已创建。SQL> create index idx_id on t(id);索引已创建。 2)至于这个问题,您可以举个反例,这样大家能更好的明白
1)count(*) 优化器会判断是否可以走索引的,如果含有主键或非空索引,那么计划就会走索引 2)如果ID列不是通常的B索引,或者该列就没有索引,那么count(ID)为统计非空和空的行总数 SQL> select count(*) from 2 (select null from dual union all 3 select 1 from dual) t; COUNT(*) ---------- 21)count(*) 优化器会判断是否可以走索引的是的、会判断、CBO会对所有可能的路线都进行判断、然后选择其中成本最低的那条去走、如果含有主键或非空索引,那么计划就会走索引你所认为的含主键走索引、也是把索引当"瘦表"来回答一个查询、至于"非空索引"这个我有点不太理解?非空?b树索引不能存空值吧2)count(ID)为统计非空和空的行总数即便不存在索引、你都认为count(id)统计总行数吗?如果是这样、我不是很赞同、 1) "非空索引” 我说的可能不太清楚,我指的是 非空约束的索引列 SQL> create table t(id int not null,nn varchar2(50));表已创建。SQL> create index idx_id on t(id);索引已创建。 2)至于这个问题,您可以举个反例,这样大家能更好的明白1) 索引里面的数据足以回答这个查询了、没有必要在回表了、这可以从你在5楼贴的执行计划看出、index full scan、CBO走这条路、把索引叶子块从左往右、一块一块、全部扫过去、索引键值就包含了select 要求的数据、所以执行计划也没有回表这个操作 2) create table t (id number,name varchar2(20)); insert into t values (1,'a'); insert into t values (2,'b'); insert into t values (null,'c'); insert into t values (4,'d'); insert into t values (null,'f'); commit; sys@ORCL> select count(*) from t; COUNT(*) ---------- 5sys@ORCL> select count(id) from t; COUNT(ID) ---------- 3 2)
COUNT(*) OR COUNT(N) 与 COUNT(ID) 首先保证正确性,其次保证效率。正确性的优先:如果id为非空或主键,则会走索引,因为等同于条件IS NOT NULL。效率的优先:如果LZ说的前提“不止一列”改为“只有一列”,则不会走索引,因为单行索引的BLOCK是大于单行的DATA的。其他如LS所言。
2)count(id)统计 id 不为 空的行、如果id列有索引、就可以走索引综上、在满足业务的情况下、第二种好、
count(*) 查询表的行数
count(id) 查询id字段非空行数
SQL> select count(*) from emp; COUNT(*)
----------
14
执行计划
----------------------------------------------------------
Plan hash value: 2937609675-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FULL SCAN| PK_EMP | 14 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------SQL> select count(empno) from emp;COUNT(EMPNO)
------------
14
执行计划
----------------------------------------------------------
Plan hash value: 2937609675-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FULL SCAN| PK_EMP | 14 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------
2)如果ID列不是通常的B索引,或者该列就没有索引,那么count(ID)为统计非空和空的行总数
SQL> select count(*) from
2 (select null from dual union all
3 select 1 from dual) t; COUNT(*)
----------
2
2)如果ID列不是通常的B索引,或者该列就没有索引,那么count(ID)为统计非空和空的行总数
SQL> select count(*) from
2 (select null from dual union all
3 select 1 from dual) t; COUNT(*)
----------
21)count(*) 优化器会判断是否可以走索引的是的、会判断、CBO会对所有可能的路线都进行判断、然后选择其中成本最低的那条去走、如果含有主键或非空索引,那么计划就会走索引你所认为的含主键走索引、也是把索引当"瘦表"来回答一个查询、至于"非空索引"这个我有点不太理解?非空?b树索引不能存空值吧2)count(ID)为统计非空和空的行总数即便不存在索引、你都认为count(id)统计总行数吗?如果是这样、我不是很赞同、
2)如果ID列不是通常的B索引,或者该列就没有索引,那么count(ID)为统计非空和空的行总数
SQL> select count(*) from
2 (select null from dual union all
3 select 1 from dual) t; COUNT(*)
----------
21)count(*) 优化器会判断是否可以走索引的是的、会判断、CBO会对所有可能的路线都进行判断、然后选择其中成本最低的那条去走、如果含有主键或非空索引,那么计划就会走索引你所认为的含主键走索引、也是把索引当"瘦表"来回答一个查询、至于"非空索引"这个我有点不太理解?非空?b树索引不能存空值吧2)count(ID)为统计非空和空的行总数即便不存在索引、你都认为count(id)统计总行数吗?如果是这样、我不是很赞同、
1) "非空索引” 我说的可能不太清楚,我指的是 非空约束的索引列
SQL> create table t(id int not null,nn varchar2(50));表已创建。SQL> create index idx_id on t(id);索引已创建。
2)至于这个问题,您可以举个反例,这样大家能更好的明白
2)如果ID列不是通常的B索引,或者该列就没有索引,那么count(ID)为统计非空和空的行总数
SQL> select count(*) from
2 (select null from dual union all
3 select 1 from dual) t; COUNT(*)
----------
21)count(*) 优化器会判断是否可以走索引的是的、会判断、CBO会对所有可能的路线都进行判断、然后选择其中成本最低的那条去走、如果含有主键或非空索引,那么计划就会走索引你所认为的含主键走索引、也是把索引当"瘦表"来回答一个查询、至于"非空索引"这个我有点不太理解?非空?b树索引不能存空值吧2)count(ID)为统计非空和空的行总数即便不存在索引、你都认为count(id)统计总行数吗?如果是这样、我不是很赞同、
1) "非空索引” 我说的可能不太清楚,我指的是 非空约束的索引列
SQL> create table t(id int not null,nn varchar2(50));表已创建。SQL> create index idx_id on t(id);索引已创建。
2)至于这个问题,您可以举个反例,这样大家能更好的明白1) 索引里面的数据足以回答这个查询了、没有必要在回表了、这可以从你在5楼贴的执行计划看出、index full scan、CBO走这条路、把索引叶子块从左往右、一块一块、全部扫过去、索引键值就包含了select 要求的数据、所以执行计划也没有回表这个操作
2)
create table t (id number,name varchar2(20));
insert into t values (1,'a');
insert into t values (2,'b');
insert into t values (null,'c');
insert into t values (4,'d');
insert into t values (null,'f');
commit;
sys@ORCL> select count(*) from t; COUNT(*)
----------
5sys@ORCL> select count(id) from t; COUNT(ID)
----------
3
2)
查询依赖于统计信息(通常是这样)以及一些基本连接,访问路径等等。
比较典型的情况COUNT(*)就是要返回所有记录,如果有索引可以用,那么oracle基本会利用索引。另COUNT(*) 和COUNT(N),n是一个常数本质上没有任何区别。至于COUNT(COL)即某个列,着得看情况,如果COL不属于现有索引的列,那么就的全表扫描,否则就可以利用索引了。而且有一点很重要的是,COUNT(COL)中COL中有空值在回被忽略。所以统计记录数和统计字段数是完全不同的概念,只是某些情况下会等价而已。能利用索引,毫无疑问会更快一些,一般情况下在大表上,索引的数据量总是比表的数量来得少一些。以上说的适合oracle10g以上。
oracle正变得越来越智能,写sql可以越来越随心所欲。
count(*) 包含空行和重复行
count(列名) 值为空时,不在统计之内
count(*) 包含空行和重复行
二者在某种情况下得到的值是相同的。count(列)在列有索引是不用全表搜索。
性能上绝对不会有什么差异,因为Oracle对这种统计有自己的一套处理方法。
再者 用不用索引 是要看 where语句
要看where这是对的。不过说count(*)和count(id)一样绝对是最大的错误。
我前面说的时候,是暂时没有考虑where的情况。
1)表是大表、肯定会有差异
2)用不用索引、不一定看索引、如果谓词没有id、id列照样走索引