MySQL 中 count() 在不同应用场景下的区别

189 阅读4分钟

在 MySQL 中 count() 函数的应用方式有 count(*)、count(1)、count(id)、count(column)。由于主键不为空,所以 count(*)、count(1)、count(id) 的结果为记录总数,而 count(column) 的结果则为记录中 column 不为 null 的行数。

本文主要介绍 count() 函数在 InnoDB 和 MyISAM 两种引擎中表现。

⓵ 对于以 InnoDB 作为引擎的数据表来说,索引和数据在同一个文件中,主键索引的叶节点存放完整的一条记录,辅助索引的叶节点则存放主键索引的值。

⓶ 对于以 MyISAM 作为引擎的数据表来说,索引文件和数据文件为两个单独的文件,无论是主键索引还是辅助索引,叶节点存放的都是数据记录的地址。

一 InnoDB

表结构

CREATE TABLE `audit_queue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `audit_id` varchar(12) DEFAULT '',
  `material_uid` varchar(36) DEFAULT NULL,
  `creative_uid` varchar(36) NOT NULL,
  `creative_group_uid` varchar(36) DEFAULT NULL,
  `creative_version` int(11) NOT NULL DEFAULT '1',
  `adx_id` int(11) NOT NULL DEFAULT '0',
  `adx_ad_id` varchar(50) DEFAULT NULL,
  `push` int(1) NOT NULL DEFAULT '0',
  `push_count` int(11) NOT NULL DEFAULT '0',
  `push_at` int(11) NOT NULL DEFAULT '0',
  `pull` int(1) NOT NULL DEFAULT '0',
  `pull_count` int(11) NOT NULL DEFAULT '0',
  `pull_at` int(11) NOT NULL DEFAULT '0',
  `status` varchar(20) NOT NULL DEFAULT '',
  `creative_status` int(1) NOT NULL DEFAULT '0',
  `result` text,
  `parsed_result` varchar(1024),
  `expire_at` int(11) NOT NULL DEFAULT '0',
  `created_at` int(11) NOT NULL DEFAULT '0',
  `created_by` varchar(36) DEFAULT NULL,
  `updated_at` int(11) NOT NULL DEFAULT '0',
  `updated_by` varchar(36) DEFAULT NULL,
  `closed` int(1) NOT NULL DEFAULT '0',
  `place_id` INT UNSIGNED DEFAULT 0  NOT NULL,
  `pull_expire_at` int(10) DEFAULT '0',
  `protocol` tinyint(4) NOT NULL DEFAULT '0',
  `title` varchar(50) NOT NULL DEFAULT '',
  `desc` varchar(200) NOT NULL DEFAULT '',
  `brand` varchar(20) NOT NULL DEFAULT '',
  `buttonText` varchar(200) NOT NULL DEFAULT '',
  `logo` varchar(50) NOT NULL DEFAULT '',
  `file1` varchar(50) NOT NULL DEFAULT '',
  `file2` varchar(50) NOT NULL DEFAULT '',
  `file3` varchar(50) NOT NULL DEFAULT '',
  `repush_at` int(11) NOT NULL DEFAULT '0',
  `width` int(11) NOT NULL DEFAULT '0',
  `height` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `audit_id` (`audit_id`),
  KEY `creative_uid` (`creative_group_uid`) USING BTREE,
  KEY `place_id` (`place_id`) USING BTREE,
  KEY `material_uid` (`material_uid`,`repush_at`,`status`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

索引结构


在没有任何过滤条件时,count(*)、count(1)、count(id) 三者没有区别


对于没有索引但是 not null 的列,如果没有过滤条件,则表现与 count(*) 相同;如果有过滤条件,且过滤条件中的列有索引,则会使用索引;如果有过滤条件,但过滤条件中的列没有索引,则不会用到索引。


对于有索引但是 not null 的列,如果没有过滤条件,则表现与 count(*) 相同;如果有过滤条件,且过滤条件中的列有索引,则会使用索引;如果有过滤条件,但过滤条件中的列没有索引,则不会用到索引。


对于没有索引但是允许为 null 的列,在没有过滤条件时不会用到索引


对于有索引但是允许为 null 的列,在没有过滤条件时会用到当前列的索引。在有过滤条件时,如果过滤条件中的列有索引,则会用到索引,否则不会用到索引。


二 MyISAM

表结构

CREATE TABLE `audit_queue` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `audit_id` varchar(12) DEFAULT '',
  `material_uid` varchar(36) DEFAULT NULL,
  `creative_uid` varchar(36) NOT NULL,
  `creative_group_uid` varchar(36) DEFAULT NULL,
  `creative_version` int(11) NOT NULL DEFAULT '1',
  `adx_id` int(11) NOT NULL DEFAULT '0',
  `adx_ad_id` varchar(50) DEFAULT NULL,
  `push` int(1) NOT NULL DEFAULT '0',
  `push_count` int(11) NOT NULL DEFAULT '0',
  `push_at` int(11) NOT NULL DEFAULT '0',
  `pull` int(1) NOT NULL DEFAULT '0',
  `pull_count` int(11) NOT NULL DEFAULT '0',
  `pull_at` int(11) NOT NULL DEFAULT '0',
  `status` varchar(20) NOT NULL DEFAULT '',
  `creative_status` int(1) NOT NULL DEFAULT '0',
  `result` text,
  `parsed_result` varchar(1024),
  `expire_at` int(11) NOT NULL DEFAULT '0',
  `created_at` int(11) NOT NULL DEFAULT '0',
  `created_by` varchar(36) DEFAULT NULL,
  `updated_at` int(11) NOT NULL DEFAULT '0',
  `updated_by` varchar(36) DEFAULT NULL,
  `closed` int(1) NOT NULL DEFAULT '0',
  `place_id` INT UNSIGNED DEFAULT 0  NOT NULL,
  `pull_expire_at` int(10) DEFAULT '0',
  `protocol` tinyint(4) NOT NULL DEFAULT '0',
  `title` varchar(50) NOT NULL DEFAULT '',
  `desc` varchar(200) NOT NULL DEFAULT '',
  `brand` varchar(20) NOT NULL DEFAULT '',
  `buttonText` varchar(200) NOT NULL DEFAULT '',
  `logo` varchar(50) NOT NULL DEFAULT '',
  `file1` varchar(50) NOT NULL DEFAULT '',
  `file2` varchar(50) NOT NULL DEFAULT '',
  `file3` varchar(50) NOT NULL DEFAULT '',
  `repush_at` int(11) NOT NULL DEFAULT '0',
  `width` int(11) NOT NULL DEFAULT '0',
  `height` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `audit_id` (`audit_id`),
  KEY `creative_uid` (`creative_group_uid`) USING BTREE,
  KEY `place_id` (`place_id`) USING BTREE,
  KEY `material_uid` (`material_uid`,`repush_at`,`status`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

索引结构


在没有任何过滤条件时,count(*)、count(1)、count(id) 三者没有区别


对于没有索引但是 not null 的列,如果没有过滤条件,则表现与 count(*) 相同;如果有过滤条件,且过滤条件中的列有索引,则会使用索引;如果有过滤条件,但过滤条件中的列没有索引,则不会用到索引。


对于有索引但是 not null 的列,如果没有过滤条件,则表现与 count(*) 相同;如果有过滤条件,且过滤条件中的列有索引,则会使用索引;如果有过滤条件,但过滤条件中的列没有索引,则不会用到索引。


对于没有索引但是允许为 null 的列,在没有过滤条件时不会用到索引


对于有索引但是允许为 null 的列,在没有过滤条件时会用到当前列的索引。在有过滤条件时,如果过滤条件中的列有索引,则会用到索引,否则不会用到索引。