【优化】COUNT(1)、COUNT(*)、COUNT(常量)、COUNT(主键)、COUNT(ROWID)、COUNT(非空列)、COUNT(允许为空列)、COUNT(DISTINCT 列名)
1.1 BLOG文档结构图
1.2 前言部分
1.2.1 导读和注意事项
各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~:
① COUNT(1)和COUNT(*)的区别(重点)
② 10046和10053的使用
③ “SELECT COUNT(列)”和“SELECT 列”在选择索引方面的区别
④ COUNT计数的优化
Tips:
① 本文在itpub(http://blog.itpub.net/26736162)、博客园(http://www.cnblogs.com/lhrbest)和微信公众号(xiaomaimiaolhr)上有同步更新。
② 文章中用到的所有代码、相关软件、相关资料及本文的pdf版本都请前往小麦苗的云盘下载,小麦苗的云盘地址见:http://blog.itpub.net/26736162/viewspace-1624453/。
③ 若网页文章代码格式有错乱,请下载pdf格式的文档来阅读。
④ 在本篇BLOG中,代码输出部分一般放在一行一列的表格中。
⑤ 本文适合于Oracle初中级人员阅读,Oracle大师请略过本文。
本文若有错误或不完善的地方请大家多多指正,您的批评指正是我写作的最大动力。
1.2.2 本文简介
看了很多有关COUNT(1)和COUNT(*)的区别和效率,众说纷纭。最终还是决定自己动手实验一番。
第二章 实验部分
2.1 实验环境介绍
|
项目 |
source db |
|
db 类型 |
RAC |
|
db version |
11.2.0.3.0 |
|
db 存储 |
ASM |
|
OS版本及kernel版本 |
RHEL 6.5 |
2.2 实验目标
弄清楚COUNT(1)、COUNT(*)、COUNT(常量)、COUNT(主键)、COUNT(ROWID)、COUNT(非空列)、COUNT(允许为空列)、COUNT(DISTINCT 列名)之间的区别,以及它们之间的效率问题。
2.3 实验过程
2.3.1 实验脚本
|
--创建1W行的表 DROP TABLE T_COUNT_LHR; CREATE TABLE T_COUNT_LHR AS SELECT OBJECT_ID, OBJECT_NAME, OWNER, DATA_OBJECT_ID, OBJECT_TYPE, LAST_DDL_TIME FROM DBA_OBJECTS D WHERE D.OBJECT_ID IS NOT NULL AND D.OBJECT_NAME IS NOT NULL AND ROWNUM <= 10000;
--更新空值, UPDATE T_COUNT_LHR t SET t.object_type='' WHERE Rownum<=5; UPDATE T_COUNT_LHR t SET t.LAST_DDL_TIME=T.LAST_DDL_TIME+ROWNUM; UPDATE T_COUNT_LHR t SET t.LAST_DDL_TIME='' WHERE Rownum<=1; COMMIT;
--添加主键、非空约束、唯一索引、普通索引 ALTER TABLE T_COUNT_LHR ADD CONSTRAINT PK_OBJECT_ID PRIMARY KEY(OBJECT_ID); ALTER TABLE T_COUNT_LHR MODIFY OBJECT_NAME NOT NULL; CREATE UNIQUE INDEX IDX_LDT ON T_COUNT_LHR(LAST_DDL_TIME); CREATE INDEX IDX_DATA_OBJECT_ID ON T_COUNT_LHR(DATA_OBJECT_ID); CREATE INDEX IDX_DATA_OWNER ON T_COUNT_LHR(OWNER); ALTER TABLE T_COUNT_LHR MODIFY OWNER NOT NULL;
--收集统计信息 EXEC dbms_stats.gather_table_stats(USER,'T_COUNT_LHR'); SELECT d.COLUMN_NAME,d.DATA_TYPE,d.NUM_NULLS,d.NUM_DISTINCT,d.LAST_ANALYZED FROM cols d WHERE d.TABLE_NAME='T_COUNT_LHR';
|
表的信息如下所示:
|
列名 |
是否主键 |
是否允许为空 |
是否有索引 |
数据类型 |
空值的行数 |
不同值的行数 |
总行数 |
|
OBJECT_ID |
Y |
N |
唯一索引 |
NUMBER |
0 |
10000 |
10000 |
|
OBJECT_NAME |
|
N |
无 |
VARCHAR2 |
0 |
8112 |
10000 |
|
OWNER |
|
N |
普通索引(IDX_OWNER) |
VARCHAR2 |
0 |
5 |
10000 |
|
DATA_OBJECT_ID |
|
Y |
普通索引(IDX_DATA_OBJECT_ID) |
NUMBER |
7645 |
2318 |
10000 |
|
OBJECT_TYPE |
|
Y |
无 |
VARCHAR2 |
5 |
20 |
10000 |
|
LAST_DDL_TIME |
|
Y |
唯一索引(IDX_LDT) |
DATE |
1 |
9999 |
10000 |
需要统计如下几种情况:
|
SELECT COUNT(1) FROM T_COUNT_LHR;--走索引 SELECT COUNT(*) FROM T_COUNT_LHR;--走索引 SELECT COUNT(ROWID) FROM T_COUNT_LHR; --走索引 SELECT COUNT(OBJECT_ID) FROM T_COUNT_LHR; --走索引 SELECT COUNT(OBJECT_NAME) FROM T_COUNT_LHR;--走索引 SELECT COUNT(OWNER) FROM T_COUNT_LHR D;--走索引 SELECT COUNT(D.DATA_OBJECT_ID) FROM T_COUNT_LHR D; --走索引 SELECT COUNT(D.LAST_DDL_TIME) FROM T_COUNT_LHR D;--走索引 SELECT COUNT(D.LAST_DDL_TIME) FROM T_COUNT_LHR D WHERE D.LAST_DDL_TIME IS NOT NULL;--走索引 SELECT D.LAST_DDL_TIME FROM T_COUNT_LHR D; --不走索引 SELECT D.LAST_DDL_TIME FROM T_COUNT_LHR D WHERE D.LAST_DDL_TIME IS NOT NULL;--走索引 SELECT COUNT(DISTINCT DATA_OBJECT_ID) FROM T_COUNT_LHR D;--不走索引 SELECT COUNT(DISTINCT OWNER) FROM T_COUNT_LHR D;--走索引 SELECT COUNT(DISTINCT DATA_OBJECT_ID) FROM T_COUNT_LHR D WHERE DATA_OBJECT_ID IS NOT NULL ;--走索引
|
2.3.2 执行计划
|
介绍 |
SQL命令 |
执行计划 |
返回行数 |
|
COUNT(1)和COUNT(常量)是一样的,SELECT COUNT(*) "COUNT(1)" FROM "LHR"."T_COUNT_LHR" "T_COUNT_LHR" |
SELECT COUNT(1) FROM T_COUNT_LHR; |
Plan hash value: 1265209789 |----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | |----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FAST FULL SCAN| PK_OBJECT_ID | 10000 | 7 (0)| 00:00:01 | |----------------------------------------------------------------------------- |
10000 |
|
SELECT COUNT(*) "COUNT(*)" FROM "LHR"."T_COUNT_LHR" "T_COUNT_LHR" |
SELECT COUNT(*) FROM T_COUNT_LHR; |
Plan hash value: 1265209789 |----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | |----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FAST FULL SCAN| PK_OBJECT_ID | 10000 | 7 (0)| 00:00:01 | |----------------------------------------------------------------------------- |
10000 |
|
SELECT COUNT("T_COUNT_LHR".ROWID) "COUNT(ROWID)" FROM "LHR"."T_COUNT_LHR" "T_COUNT_LHR" |
SELECT COUNT(ROWID) FROM T_COUNT_LHR; |
Plan hash value: 1265209789 |------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | |------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 12 | 7 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 12 | | | | 2 | INDEX FAST FULL SCAN| PK_OBJECT_ID | 10000 | 117K| 7 (0)| 00:00:01 | |------------------------------------------------------------------------------------- |
10000 |
|
SELECT COUNT(*) "COUNT(OBJECT_ID)" FROM "LHR"."T_COUNT_LHR" "T_COUNT_LHR" |
SELECT COUNT(OBJECT_ID) FROM T_COUNT_LHR; |
Plan hash value: 1265209789 |----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | |----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FAST FULL SCAN| PK_OBJECT_ID | 10000 | 7 (0)| 00:00:01 | |----------------------------------------------------------------------------- |
10000 |
|
SELECT COUNT(*) "COUNT(OBJECT_NAME)" FROM "LHR"."T_COUNT_LHR" "T_COUNT_LHR" |
SELECT COUNT(OBJECT_NAME) FROM T_COUNT_LHR; |
Plan hash value: 1265209789 |----------------------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | |----------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 7 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | | | | 2 | INDEX FAST FULL SCAN| PK_OBJECT_ID | 10000 | 7 (0)| 00:00:01 | |----------------------------------------------------------------------------- |
10000 |
|
OWNER列含有索引,非空列,选择主键索引 |
SELECT COUNT(OWNER) FROM T_COUNT_LHR D; |
Plan hash value: 1265209789 |----------------------------------------------------------------------------- | Id | Operation | Name   |