count(*)、count(val)和count(1)的解释
一、关于count的一些谣言:
1、count(*)比count(val)更慢!项目组必须用count(val),不准用count(*),谁用扣谁钱!
2、count(*)用不到索引,count(val)才能用到。
3、count(*)是统计出全表的记录,是吞吐量的操作,肯定用不到索引。
4、count(1)比count(*)的速度快。
二、验证count(*)和count(val)
1、首先创建一个表,使用count(*)和count(val)查询比较:
----删除echo表----
SQL> drop table echo purge;
drop table echo purge
*
第 1 行出现错误:
ORA-00942: 表或视图不存在 ----创建一张echo的测试表----
SQL> create table echo as select * from dba_objects; 表已创建。 SQL> update echo set object_id = rownum; 已更新72509行。 SQL> commit; 提交完成。 SQL> set timing on
SQL> set linesize 100
SQL> set autotrace on
SQL> select count(*) from echo; COUNT(*)
----------
72509 已用时间: 00: 00: 00.01 执行计划
----------------------------------------------------------
Plan hash value: 99109176 -------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 290 (1)| 00:00:04 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| ECHO | 80064 | 290 (1)| 00:00:04 |
------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
4 recursive calls
0 db block gets
1265 consistent gets
0 physical reads
11060 redo size
425 bytes sent via SQL*Net to client
415 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 echo; COUNT(*)
----------
72509 已用时间: 00: 00: 00.01 执行计划
----------------------------------------------------------
Plan hash value: 99109176 -------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 290 (1)| 00:00:04 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| ECHO | 80064 | 290 (1)| 00:00:04 |
------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
1038 consistent gets
0 physical reads
0 redo size
425 bytes sent via SQL*Net to client
415 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(object_id) from echo; COUNT(OBJECT_ID)
----------------
72509 已用时间: 00: 00: 00.01 执行计划
----------------------------------------------------------
Plan hash value: 99109176 ---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 290 (1)| 00:00:04 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
| 2 | TABLE ACCESS FULL| ECHO | 80064 | 1016K| 290 (1)| 00:00:04 |
--------------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
4 recursive calls
0 db block gets
1112 consistent gets
0 physical reads
0 redo size
433 bytes sent via SQL*Net to client
415 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(object_id) from echo; COUNT(OBJECT_ID)
----------------
72509 已用时间: 00: 00: 00.01 执行计划
----------------------------------------------------------
Plan hash value: 99109176 ---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 290 (1)| 00:00:04 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
| 2 | TABLE ACCESS FULL| ECHO | 80064 | 1016K| 290 (1)| 00:00:04 |
--------------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
1038 consistent gets
0 physical reads
0 redo size
433 bytes sent via SQL*Net to client
415 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(val)是一样快的。
2、建立索引做比较
SQL> create index idx_object_id on echo(object_id); 索引已创建。 已用时间: 00: 00: 05.69
SQL> select count(*) from echo; COUNT(*)
----------
72509 已用时间: 00: 00: 00.05 执行计划
----------------------------------------------------------
Plan hash value: 99109176 -------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 290 (1)| 00:00:04 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| ECHO | 80064 | 290 (1)| 00:00:04 |
------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
5 recursive calls
0 db block gets
1113 consistent gets
0 physical reads
0 redo size
425 bytes sent via SQL*Net to client
415 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(object_id) from echo; COUNT(OBJECT_ID)
----------------
72509 已用时间: 00: 00: 00.08 执行计划
----------------------------------------------------------
Plan hash value: 1131838604 ---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 49 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
| 2 | INDEX FAST FULL SCAN| IDX_OBJECT_ID | 80064 | 1016K| 49 (0)| 00:00:01 |
--------------------------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
4 recursive calls
0 db block gets
244 consistent gets
161 physical reads
0 redo size
433 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
哇,原来真的是用count(val)比count(*)要快啊,因为count(*)不能用到索引,而count(val)可以,真相真是如此吗?
3、将object_id设置为非空
SQL> alter table echo modify object_id not null; 表已更改。 已用时间: 00: 00: 01.41 SQL> select count(*) from echo; COUNT(*)
----------
72509 已用时间: 00: 00: 00.00 执行计划
----------------------------------------------------------
Plan hash value: 1131838604 -------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 49 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FAST FULL SCAN| IDX_OBJECT_ID | 80064 | 49 (0)| 00:00:01 |
------------------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
169 consistent gets
0 physical reads
0 redo size
425 bytes sent via SQL*Net to client
415 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(object_id) from echo; COUNT(OBJECT_ID)
----------------
72509 已用时间: 00: 00: 00.01 执行计划
----------------------------------------------------------
Plan hash value: 1131838604 -------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 49 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | INDEX FAST FULL SCAN| IDX_OBJECT_ID | 80064 | 49 (0)| 00:00:01 |
------------------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
169 consistent gets
0 physical reads
0 redo size
433 bytes sent via SQL*Net to client
415 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
--看来count(val)和count(*)其实一样快,如果索引列是非空的,count(*)可用到索引,此时一样快!真相真是如此吗?
其实两者根本没有可比性,性能比较首先考虑写法等价,这两个语句根本就不等价。
结论:
其实优化器里的算法是这么玩的,列的偏移量决定性能,列越靠后,访问的开销越大。由于count(*)的算法与列偏移量无关,所以count(*)最快,count(最后列val)最慢。
3、用实验验证上面的结论:
SQL> set serveroutput on
SQL> set echo on
SQL> drop table t purge; 表已删除。
----构造出有25个字段的表T----
DECLARE
l_sql VARCHAR2(32767);
BEGIN
l_sql := 'CREATE TABLE t (';
FOR i IN 1..25
LOOP
l_sql := l_sql || 'n' || i || ' NUMBER,';
END LOOP;
l_sql := l_sql || 'pad VARCHAR2(1000)) PCTFREE 10';
EXECUTE IMMEDIATE l_sql;
END;
12 / PL/SQL 过程已成功完成。
----将记录还有这个表T中填充----
DECLARE
l_sql VARCHAR2(32767);
BEGIN
l_sql := 'INSERT INTO t SELECT ';
FOR i IN 1..25
LOOP
l_sql := l_sql || '0,';
END LOOP;
l_sql := l_sql || 'NULL FROM dual CONNECT BY level <= 10000';
EXECUTE IMMEDIATE l_sql;
COMMIT;
END;
13 / PL/SQL 过程已成功完成。 execute dbms_stats.gather_table_stats(ownname=>user, tabname=>'t')
SELECT num_rows, blocks FROM user_tables WHERE table_name = 'T'; PL/SQL 过程已成功完成。 SQL>
NUM_ROWS BLOCKS
---------- ----------
10000 80
----以下动作观察执行速度,比较发现count(*)最快,count(最大列)最慢----
SQL> DECLARE
l_dummy PLS_INTEGER;
l_start PLS_INTEGER;
l_stop PLS_INTEGER;
l_sql VARCHAR2(100);
BEGIN
l_start := dbms_utility.get_time;
FOR j IN 1..1000
LOOP
EXECUTE IMMEDIATE 'SELECT count(*) FROM t' INTO l_dummy;
END LOOP;
l_stop := dbms_utility.get_time;
dbms_output.put_line((l_stop-l_start)/100);
14
FOR i IN 1..25
LOOP
l_sql := 'SELECT count(n' || i || ') FROM t';
l_start := dbms_utility.get_time;
FOR j IN 1..1000
LOOP
EXECUTE IMMEDIATE l_sql INTO l_dummy;
END LOOP;
l_stop := dbms_utility.get_time;
dbms_output.put_line((l_stop-l_start)/100);
END LOOP;
END;
27 /
.18
.33
.39
.38
.42
.4
.45
.49
.48
.46
.48
.48
.55
.51
.56
.57
.61
.62
.75
.67
.68
.7
.73
.78
.77
.81
PL/SQL 过程已成功完成。
三、验证count(*)和count(1)
沿用TOM大师的解释:
count(*)、count(val)和count(1)的解释的更多相关文章
- SQLSERVER 里SELECT COUNT(1) 和SELECT COUNT(*)哪个性能好?
SQLSERVER 里SELECT COUNT(1) 和SELECT COUNT(*)哪个性能好? 今天遇到某人在我以前写的一篇文章里问到 如果统计信息没来得及更新的话,那岂不是统计出来的数据时错误的 ...
- COUNT(*),count(1),COUNT(ALL expression),COUNT(DISTINCT expression)
创建一个测试表 IF OBJECT_ID( 'dbo.T1' , 'U' )IS NOT NULL BEGIN DROP TABLE dbo.T1; END; GO )); GO INSERT INT ...
- hql中不能写count(1)能够写count(a.id)
hql中不能写count(1)能够写count(a.id)里面写详细的属性 String hql="select new com.haiyisoft.vo.entity.cc.repo.Bu ...
- count(*)、count(1)和count(列名)的区别
count(*).count(1)和count(列名)的区别 1.执行效果上: l count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL l count(1)包 ...
- 今天犯了个小错误:_dataArray.count>1 和_dataArray.count>0搞混淆了
_dataArray.count>1 和_dataArray.count>0搞混淆了:当数据为一条时,条件不成立.应该_dataArray.count>=1 或者>0 ( ...
- COUNT(*)、COUNT(主键)、COUNT(1)
MyISAM引擎,记录数是结构的一部分,已存cache在内存中; InnoDB引擎,需要重新计算,id是主键的话,会加快扫描速度: 所以select count(*) MyISAM完胜! MyISA ...
- 【优化】COUNT(1)、COUNT(*)、COUNT(常量)、COUNT(主键)、COUNT(ROWID)、COUNT(非空列)、COUNT(允许为空列)、COUNT(DISTINCT 列名)
[优化]COUNT(1).COUNT(*).COUNT(常量).COUNT(主键).COUNT(ROWID).COUNT(非空列).COUNT(允许为空列).COUNT(DISTINCT 列名) 1. ...
- oracle count(*) 和count(列)性能
一直以为oracle中count(列)比count(*) 快,这篇文件解释了一下: http://blog.csdn.net/szstephenzhou/article/details/8446481
- COUNT(*),count(1),COUNT(ALL expression),COUNT(DISTINCT expression) BY Group by
select column_2,count(column_2) as 'count(column_2)' ,count(column_1) as 'count(column_1)' ,count(*) ...
随机推荐
- pptp建立vpn
1. 安装依赖 ppp yum -y install ppp 2. 编译安装pptpd wget http://jaist.dl.sourceforge.net/project/poptop/pptp ...
- c#:拖动功能
需求:放在图层上一个图片,要实现鼠标可以选中,并实现拖放功能. 需求分析: 1.采用winform方式实现: 2.需要一个PictureBox对象,对该PictureBox添加MouseMove,Mo ...
- .NET业务实体类验证组件Fluent Validation
认识Fluent Vaidation. 看到NopCommerce项目中用到这个组建是如此的简单,将数据验证从业务实体类中分离出来,真是一个天才的想法,后来才知道这个东西是一个开源的轻量级验证组建. ...
- Linux内核源码分析方法
一.内核源码之我见 Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次.如果想透析Linux,深入操作系统的本质,阅读内核源码是最有效的途径.我们都 ...
- Lintcode: Majority Number III
Given an array of integers and a number k, the majority number is the number that occurs more than 1 ...
- NGINX反向代理
Nginx反向代理 ...
- ACM之Java速成(1)
这里指的java速成,只限于java语法,包括输入输出,运算处理,字符串和高精度的处理,进制之间的转换等,能解决OJ上的一些高精度题目. 1. 输入: 格式为:Scanner cin = new Sc ...
- [原创]java WEB学习笔记81:Hibernate学习之路--- 对象关系映射文件(.hbm.xml):hibernate-mapping 节点,class节点,id节点(主键生成策略),property节点,在hibernate 中 java类型 与sql类型之间的对应关系,Java 时间和日期类型的映射,Java 大对象类型 的 映射 (了解),映射组成关系
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- 用Appium去操作移动设备上的chrome
最近在积极努力的学习Appium,今天成功运行了官网上的demo,在此做一个小小的总结: 前期准备工作: (1)在要运行的真机或模拟器上安装chrome. 注意:x86的虚拟机是不支持的,但是经过本人 ...
- Codeforces Round #312 (Div. 2) E. A Simple Task
题目大意就是给一个字符串,然后多个操作,每次操作可以把每一段区间的字符进行升序或者降序排序,问最终的字符串是多少. 一开始只考虑字符串中字符'a'的情况,假设操作区间[L,R]中有x个'a',那么一次 ...