COUNT系列

优化】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:

本文适合于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.4  实验结论

COUNT()函数是Oracle中的聚合函数,用于统计结果集的行数。其语法形式如下所示:


COUNT({ * | [ DISTINCT | ALL ] expr }) [ OVER (analytic_clause) ]

COUNT returns the number of rows returned by the query. You can use it as an aggregate or analytic function.

If you specify DISTINCT, then you can specify only the query_partition_clause of the analytic_clause. The order_by_clause and windowing_clause are not allowed.

If you specify expr, then COUNT returns the number of rows where expr is not null. You can count either all rows, or only distinct values of expr.

If you specify the asterisk (*), then this function returns all rows, including duplicates and nulls. COUNT never returns null.

我们把COUNT的使用情况分为以下3类:

① COUNT(1)、COUNT(*)、COUNT(常量)、COUNT(主键)、COUNT(ROWID)、COUNT(非空列)

② COUNT(允许为空列)

③ COUNT(DISTINCT 列名)

下面分别从查询结果和效率方面做个比较:

(一)结果区别

① COUNT(1)、COUNT(*)、COUNT(ROWID)、COUNT(常量)、COUNT(主键)、COUNT(非空列)这几种方式统计的行数是表中所有存在的行的总数,包括值为NULL的行和非空行。所以,这几种方式的执行结果相同。这里的常量可以为数字或字符串,例如,COUNT(2)、COUNT(333)、COUNT(‘x‘)、COUNT(‘xiaomaimiao‘)。需要注意的是:这里的COUNT(1)中的“1”并不表示表中的第一列,它其实是一个表达式,可以换成任意数字或字符或表达式。

② COUNT(允许为空列) 这种方式统计的行数不会包括字段值为NULL的行。

③ COUNT(DISTINCT 列名) 得到的结果是除去值为NULL和重复数据后的结果。

④ “SELECT COUNT(‘‘),COUNT(NULL) FROM T_COUNT_LHR;”返回0行。

(二)效率、索引

① 如果存在主键或非空列上的索引,那么COUNT(1)、COUNT(*)、COUNT(ROWID)、COUNT(常量)、COUNT(主键)、COUNT(非空列)会首先选择主键上的索引快速全扫描(INDEX FAST FULL SCAN)。若主键不存在则会选择非空列上的索引。若非空列上没有索引则肯定走全表扫描(TABLE ACCESS FULL)。其中,COUNT(ROWID)在走索引的时候比其它几种方式要慢。通过10053事件可以看到这几种方式除了COUNT(ROWID)之外,其它最终都会转换成COUNT(*)的方式来执行。

② 对于COUNT(COL1)来说,只要列字段上有索引则会选择索引快速全扫描(INDEX FAST FULL SCAN)。而对于“SELECT COL1”来说,除非列上有NOT NULL约束,否则执行计划会选择全表扫描。

③ COUNT(DISTINCT 列名) 若列上有索引,且有非空约束或在WHERE子句中使用IS NOT NULL,则会选择索引快速全扫描。其余情况选择全表扫描。



About Me


...............................................................................................................................

● 本文作者:小麦苗,只专注于数据库的技术,更注重技术的运用

● 本文在itpub(http://blog.itpub.net/26736162)、博客园(http://www.cnblogs.com/lhrbest)和个人微信公众号(xiaomaimiaolhr)上有同步更新

● 本文itpub地址:http://blog.itpub.net/26736162/viewspace-2136339/

● 本文博客园地址:http://www.cnblogs.com/lhrbest

● 本文pdf版及小麦苗云盘地址:http://blog.itpub.net/26736162/viewspace-1624453/

● QQ群:230161599     微信群:私聊

● 联系我请加QQ好友(646634621),注明添加缘由

● 于 2017-03-28 09:00 ~ 2017-03-30 22:00 在魔都完成

● 文章内容来源于小麦苗的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解

● 版权所有,欢迎分享本文,转载请保留出处

...............................................................................................................................

拿起手机使用微信客户端扫描下边的左边图片来关注小麦苗的微信公众号:xiaomaimiaolhr,扫描右边的二维码加入小麦苗的QQ群,学习最实用的数据库技术。

时间: 2024-10-11 06:57:37

COUNT系列的相关文章

nodejs api 中文文档

文档首页 英文版文档 本作品采用知识共享署名-非商业性使用 3.0 未本地化版本许可协议进行许可. Node.js v0.10.18 手册 & 文档 索引 | 在单一页面中浏览 | JSON格式 目录 关于本文档 稳定度 JSON 输出 概述 全局对象 global process console 类: Buffer require() require.resolve() require.cache require.extensions __filename __dirname module e

Stream系列(十)Count方法使用

计数器 视频讲解: https://www.bilibili.com/video/av77905733/ EmployeeTestCase.java package com.example.demo; import lombok.extern.log4j.Log4j2; import org.junit.Test; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Files; import

[LeetCode]Count Primes

题目:Count Primes 统计1-n的素数的个数. 思路1: 通常的思想就是遍历(0,n)范围内的所有数,对每个数i再遍历(0,sqrt(i)),每个除一遍来判断是否为素数,这样时间复杂度为O(n*sqrt(n)). 具体实现不在贴代码,过程很简单,两重循环就可以解决.但是效率很差,n较大时甚至会花几分钟才能跑完. 思路2: 用埃拉特斯特尼筛法的方法来求素数,时间复杂度可以达到O(nloglogn). 首先开一个大小为n的数组prime[],从2开始循环,找到一个质数后开始筛选出所有非素数

Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例

概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3534050.html Semaphore简介 Semaphore是一个计数信号量,它的本质是一个"共享锁". 信号量维护了一个信号量许可集.线程可以通过调用acquire()来获取信号量的许可

MongoDB系列教程(八):GridFS存储详解

MongoDB系列教程(八):GridFS存储详解 GridFS简介 mongoDB的文档以BSON格式存储,支持二进制的数据类型,当我们把二进制格式的数据直接保存到mongoDB的文档中.但是当文件太大时,例如图片和视频等文件,每个文档的长度是有限的,于是mongoDb会提供了一种处理大文件的规范--GridFS. GridFS实现原理 在GridFS数据库中,默认使用fs.chunks 和fs.files来存储文件,其中fs.files集合存放文件的信息,fs.chunks存放文件的数据,一

[算法系列之二十]字典树(Trie)

一 概述 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 二 优点 利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希表高. 三 性质 (1)根节点不包含字符,除根节点外每一个节点都只包含一个字符: (2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串: (3)每个节点的所有子节点包含的字符都不相同. 单词列表为"apps&

Irrlicht 3D Engine 笔记系列 之 自己定义Animator

作者: i_dovelemon 日期: 2014 / 12 / 17 来源: CSDN 主题: Custom Animator, Referenced count 引言 在昨天的文章<Irrlicht 3D Engine 笔记系列 之 教程4 - Movement>中,博主向大家保证会在今天向大家实际操作怎样扩展Irrlicht引擎的Animator特性.假设读者对Irrlicht的Animator的特性不是非常了解的话,请先了解下前面的那篇文章,本片文章是在上次文章的基础上进行的. Cust

NLP系列(4)_朴素贝叶斯实战与进阶(转)

http://blog.csdn.net/han_xiaoyang/article/details/50629608 作者: 寒小阳 && 龙心尘 时间:2016年2月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/50629608 http://blog.csdn.net/longxinchen_ml/article/details/50629613 声明:版权所有,转载请联系作者并注明出处 1.引言 前两篇博文介绍了朴素贝叶

【锁】Oracle锁系列

[锁]Oracle锁系列 1  BLOG文档结构图 2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 锁的概念.分类.及其模拟 ② 查询锁的视图及视图之间的关联 ③ 锁的参数(DML_LOCKS.DDL_LOCK_TIMEOUT) ④ FOR UPDATE及FOR UPDATE OF系列 ⑤ 带ONLINE和不带ONLINE创建索引的锁情况(是否阻塞DML操作) ⑥ 包或存过不能编译的解决方法