C/C++教程

重新认识康特星count(*)和康特伊count(1)

本文主要是介绍重新认识康特星count(*)和康特伊count(1),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

MyISAM引擎表

康特星count(*)

孤独的count(*)

含其他列的康特星count(*)

含where子句的康特星count(*)

康特伊count(1)

孤独的count(1)

count(name)

count(distinct name)

 InnoDB引擎表

康特星count(*)

孤独的count(*)

康特伊count(1) 

孤独的count(1)


        本文主要讨论MySQL中count(*)和count(1)的一些区别。实验基于如下MySQL版本:

MyISAM引擎表

        先创建一张无任何索引的MyISAM引擎表myisam_test,表创建语句如下:

DROP TABLE IF EXISTS myisam_test;
CREATE TABLE `myisam_test` (
  name varchar(50) DEFAULT NULL,
  age int DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

准备4条测试数据(其中有两条相同),如下:

insert into myisam_test (name,age) values
(null,null),
('zhangsan',23),
('',null),
('zhangsan',23);
SELECT * FROM myisam_test;

 如图:


康特星count(*)

孤独的count(*)

        执行不含其他列且没有where子句的count(*),查询语句如下:

select count(*) from myisam_test;

查询到4条记录,如图:

 发现无论是null值或者值相同的行都计算在内,结果返回了表的所有行数。我们添加explain后,查看该查询语句的执行计划如下:

explain select count(*) from myisam_test;

 从执行计划中可以看到,type列的值null,Extra列的值为Select tables optimized away,意思是“选择最优化的表”,因为存储引擎MyISAM存储了当前表的准确的行数,可以非常快速的直接访问,无需扫描记录。

含其他列的康特星count(*)

        我们根据name字段分组统计,如下:

select name, count(*) from myisam_test group by name;

执行结果如下:

和预期一样,我们如下查看执行计划,如下:

 结果很糟糕,首先进行了全表扫描,并且使用了临时表和排序,性能低下。

含where子句的康特星count(*)

         执行如下查询语句

select count(*) from myisam_test where name='zhangsan';

结果如图:

 查看执行计划,如下: 

 可以看到进行了全表扫描,使用where子句进行了过滤,性能也比较低。


康特伊count(1)

孤独的count(1)

        执行不包含其他列和where子句的count(1),查询语句如下:

select count(1) from myisam_test;

执行结果如图:

 继续查看执行计划,如图:

发现和康特星无任何区别。 

        综上所述,对于MyISAM引擎表,康特星和康特伊并无区别。


count(name)

        如果我们将星号替换成列,看结果如何?执行如下查询,统计name的数量:

select count(name) from myisam_test;

执行结果如图:

原表中总共4条记录,统计结果为3条,忽略了name为null的记录。 

如图,查看执行计划: 

 发现count(name)也是全表扫描。


count(distinct name)

        查询语句如下:

select count(distinct name) from myisam_test;

 执行结果如图:

 

从结果来看, 忽略了name值为null的记录,且多个name值相同的记录仅计数1次。执行计划如下:


 InnoDB引擎表

         前面我们认识了MyISAM引擎表,现在我们来看下无任何索引的InnoDB引擎表innodb_test,创建语句如下:

drop table if exists innodb_test;
CREATE TABLE `innodb_test` (
  `name` varchar(50) DEFAULT null,
    age int DEFAULT null
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

准备4条测试数据(其中有两条相同),如下:

insert into innodb_test(name,age) values
(null,null),
('zhangsan',23),
('',null),
('zhangsan',23);
select * from innodb_test;

 如图:


康特星count(*)

孤独的count(*)

        执行如下查询

select count(*) from innodb_test;

结果如图: 

 

 查看执行计划,如图

康特星走的是全表扫描。那么为什么不和MyISAM引擎一样,存储表的总行数直接返回呢?因为InnoDB是事务性存储引擎,并发事务可能同时“看到”不同的行数。因此,SELECT COUNT(*)语句只计数当前事务可见的行。 关于事务隔离可参见本文作者其他文章,此处不累述。


康特伊count(1) 

孤独的count(1)

        执行如下查询语句

select count(1) from innodb_test;

结果如图:

 查看执行计划:

 发现查询走的是全表扫描。

        综上所述,总结如下:

无任何索引的MyISAM引擎表无任何索引的InnoDB引擎表
count(*)

返回表总行数;

直接返回引擎存储的行数;

返回表总行数;

全表扫描;

含其他列count(*)

返回该列各个值的行数;

全表扫描,创建临时表和排序;

返回该列各个值的行数;

全表扫描;

含where子句count(*)

返回符合where条件的行数;

全表扫描,使用where过滤;

返回符合where条件的行数;

全表扫描,使用where过滤;

count(name)

返回name不为null的总行数;

全表扫描;

返回name不为null的总行数;

全表扫描;
count(distinct name)

返回name不为null且不同的总行数;

全表扫描;

返回name不为null且不同的总行数;

全表扫描;

count(1)同count(*)同count(*)
含其他列count(1)同count(*)同count(*)
含where子句count(1)同count(*)同count(*)

本文未讨论表含有索引的情况。

这篇关于重新认识康特星count(*)和康特伊count(1)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!