select count(*)、count(1)、count(主键列)和count(包含空值的列)有何区别?

下班路上看见网上有人问一个问题:

oracle 10g以后count(*)和count(非空列)性能方面有什么区别?

乍一看,确实有些含糊,Oracle中往往小问题蕴含着大智慧,如何破云见日?

最直接的方法,我想就是通过10053事件,来看下不同SQL对应的执行计划和资源消耗等情况,进而看看是否有些信息可以为我们所用。

首先,准备测试数据,11g库表bisal的id1列是主键(确保id1列为非空),id2列包含空值,

我们分别用10053打印如下4组SQL的trace,

SQL1:select count(*) from bisal;
SQL2:select count(1) from bisal;
SQL3:select count(id1) from bisal;
SQL4:select count(id2) from bisal;

我们来看下这四个SQL的执行结果,

前三个均为表数据总量,第四个SQL结果是99999,仅包含非空记录数据量,说明若使用count(允许空值的列),则统计的是非空记录的总数,空值记录不会统计,这可能和业务上的用意不同。

我们在看下这四个SQL对应的执行计划,前三个SQL执行计划相同,均为对主键索引的快速索引全扫描,

第四个SQL执行计划,则是全表扫描,

其实这无论id2是否包含空值,使用count(id2)均会使用全表扫描,因此即使语义上使用count(id2)和前三个SQL一致,这种执行计划的效率也是最低的,这张测试表的字段设置和数据量不很夸张,因此不很明显,如果数据表字段多、数据量大,显然主键索引占用的数据块要比数据表占用的数据块少,因此仅索引扫描,而且是全索引快速扫描(多块读),消耗的资源会更少些了。

再看前三个SQL对应的trace,第1个SQL,

第二个SQL,

第三个SQL,

可以看出一个问题,就是这三个SQL经过Oracle转换,执行的SQL其实都是select count(*) from bisal,因此对应的执行计划成本选择,这三个SQL相同,

比较了全表扫描、索引快速全扫描以及全索引扫描这三种扫描方式的成本,都选择了主键索引的FFS扫描方式。

总结:
11g下,通过实验结论,说明了count()、count(1)和count(主键索引字段)其实都是执行的count(),而且会选择索引的FFS扫描方式,count(包含空值的列)这种方式一方面会使用全表扫描,另一方面不会统计空值,因此有可能和业务上的需求就会有冲突,因此使用count统计总量的时候,要根据实际业务需求,来选择合适的方法,避免语义不同。

欢迎关注我的个人微信公众号:bisal的个人杂货铺

时间: 2024-08-01 00:07:33

select count(*)、count(1)、count(主键列)和count(包含空值的列)有何区别?的相关文章

深入探寻mysql自增列导致主键重复问题的原因_Mysql

废话少说,进入正题.      拿到问题后,首先查看现场,发现问题表的中记录的最大值比自增列的值要大,那么很明显,当有记录进行插入时,自增列产生的值就有可能与已有的记录主键冲突,导致出错.首先想办法解决问题,通过人工调大自增列的值,保证大于表内已有的主键即可,调整后,导数据正常.问题是解决了,接下来要搞清楚问题原因,什么操作导致了这种现象的发生呢?       这里有一种可能,即业务逻辑包含更新自增主键的代码,由于mysql的update动作不会同时更新自增列值,若更新主键值比自增列大,也会导致

oracle的主键约束添加删除

oracle的主键约束添加删除 1.创建表的同时创建主键约束一.无命名create table accounts (accounts_number number primary key,accounts_balance number);二.有命名 create table accounts (accounts_number number primary key,accounts_balance number,constraint yy primary key(accounts_number));

数据库自增主键可能产生的问题

在MySQL中经常会配置自增长属性的字段作为主键,特别是使用InnoDB存储引擎, 因为InnoDB的聚集索引的特性,使用自增长属性的字段当主键性能更好,但是使用自增主键也可能会带来一些问题. 举个例子,使用自增主键对数据库做分库分表,可能出现一些诸如主键重复等的问题,或者在数据库导入的时候,可能会因为主键出现一些问题. 主要业务表的主键应该配置一个合理的策略,尽量避免自增AUTO_INCREMENT. 针对主键自增可能产生的问题,下面这两篇文章有相关的讨论: INNODB自增主键的一些问题my

MySQL主键设计

原文:MySQL主键设计 [TOC] 在项目过程中遇到一个看似极为基础的问题,但是在深入思考后还是引出了不少问题,觉得有必要把这一学习过程进行记录. MySQL主键设计原则 MySQL主键应当是对用户没有意义的. MySQL主键应该是单列的,以便提高连接和筛选操作的效率 永远也不要更新MySQL主键 MySQL主键不应包含动态变化的数据,如时间戳.创建时间列.修改时间列等 MySQL主键应当有计算机自动生成. 主键设计的常用方案 自增ID 优点: 1.数据库自动编号,速度快,而且是增量增长,聚集

JPA中的主键生成策略

Table 策略 (Table strategy) 这种策略中,持久化引擎 (persistence engine) 使用关系型数据库中的一个表 (Table) 来生成主键.这种策略可移植性比较好,因为所有的关系型数据库都支持这种策略.不同的 J2EE 应用服务器使用 不同的持久化引擎. 下面用一个例子来说明这种表生成策略的使用: 清单 1.Table 生成策略 @Entity public class PrimaryKey_Table { @TableGenerator(name = "PK_

论 mysql 主键

什么是主键: 表中经常有一个列或列的组合,其值能唯一地标识表中的每一行.这样的一列或多列称为表的主键,通过它可强制表的实体完整性.当创建或更改表时可通过定义 PRIMARY KEY 约束来创建主键.一个表只能有一个 PRIMARY KEY 约束,而且 PRIMARY KEY 约束中的列不能接受空值.由于 PRIMARY KEY 约束确保唯一数据,所以经常用来定义标识列. 作用: 1)保证实体的完整性; 2)加快数据库的操作速度 3) 在表中添加新记录时,mysql会自动检查新记录的主键值,不允许

【优化】COUNT(1)、COUNT(*)、COUNT(常量)、COUNT(主键)、COUNT(ROWID)等

[优化]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的使用 ③ "SELEC

C#中两个具有相同主键,但是其他列不同的datatable怎么合并成一个啊.

问题描述 C#中两个具有相同主键,但是其他列不同的datatable怎么合并成一个啊. 查到了一些要么是两个表完全相同,要么是完全不同...这种有一列相同的怎么写啊 解决方案 用linq from x in dt1.AsEnumerable() join y in dt2.AsEnumerable() on x.Field<int>("id") equals y.Field<int>("id") select new { x, y }; 解决

Oracle 数据库针对表主键列并发导致行级锁简单演示_oracle

本文内容 •软件环境 •简单演示 Oracle 数据库并发导致行级锁 本文简单演示针对表主键并发导致的行级锁.并发是两个以上的用户对同样的数据进行修改(包括插入.删除和修改).锁的产生是因为并发.没有并发,就没有锁.并发的产生是因为系统需要,系统需要是因为用户需要. 软件环境 -------------------------------------------------------------------------------- •Windows 2003 Server •Oracle 1