jrs直播nba播

admin · 2009-07-01

  

  本日有人跟我讲 MySQL 中 count(1) 比 count(*) 疾,这能忍?必需得和他掰扯掰扯。

  申明:如下接洽基于 InnoDB 存储引擎,MyISAM 由于处境特别我正在文末会独自说一下。

  先说论断:这两个功能不同不大。

   1.推行

  我筹备了一张有 100W 条数据的外,外构造如下:

  

CREATETABLE`user`(`id`int(11)unsignedNOTNULLAUTO_INCREMENT,`username`varchar(255)DEFAULTNULL,`address`varchar(255)DEFAULTNULL,`password`varchar(255)DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4;

 

  可能看到,有一个主键索引。

  咱们来用两种体例统计一下外中的记载数,如下:

  

  可能看到,两条 SQL 的施行出力本来差不众,都是 0.14s。

  再来看其它两个统计:

  

  id 是主键,username 以及 address 则是广泛字段。

  可能看出,用 id 来统计,也有一丢丢上风。松哥这里由于测试数据样板斗劲小,是以恶果不明白,小搭档们可能加大测试数据量,那末这类区别会越发明白。

  那末究竟是甚么出处变成的这类区别,接上去咱们就来纯洁说明一下。

   2. explain 说明

  咱们先用 explain 来看下这几个 SQL 分别的施行预备:

  

  可能看到,前三个统计体例的施行预备是相同的,前面两个是相同的。

  我这里和大众斗劲下 explain 中的分别项:

   type:前三个的 type 值为 index,吐露全索引扫描,便是把全面索引过一遍就行(细心是索引不是全面外);后两个的 type 值为 all,吐露全外扫描,即不会运用索引。 key:这个吐露 MySQL 决意采取哪一个索引来优化对该外的接见,PRIMARY 吐露诈骗主键索引,NULL 吐露不消索引。 key_len:这个吐露 MySQL 运用的键长度,由于咱们的主键范例是 INT 且非空,是以值为 4。 Extra:这其中的 Using index 吐露优化器只要要经由过程接见索引便可能获取到必要的数据(没必要要回外)。

  经由过程 explain 咱们本来也能大意看出来前三种统计体例的施行出力是要高少许的(由于用到了索引),而前面两种的统计出力绝对来讲要低少许的(没用索引,必要全外扫描)。

  唯一下面的说明还不敷,咱们再来从道理角度来说明一下。

   3. 道理说明 3.1 主键索引与广泛索引

  正在先河道理说明从前,我思先率领大众看一下 B+ 树,这对付咱们贯通接上去的实质有厉重效用。

  大众都了然,InnoDB 中索引的存储构造都是 B+ 树(至于甚么是 B+ 树,和 B 树有甚么差别,这个本文就不接洽了,这两个独自都能整出来一篇著作),主键索引和广泛索引的存储又有所分别,如下图吐露主键索引:

  

  可能看到,正在主键索引中,叶子结点生存了每一行的数据。

  而正在广泛索引中,叶子结点生存的是主键值,当咱们运用广泛索引去寻求数据的岁月,先正在叶子结点中找到主键,再拿着主键去主键索引中查找数据,相称于做了两次查找,这也便是咱们往常所说的回外操纵。

   3.2 道理说明

  不了然小搭档们有没有细心过,咱们研习 MySQL 的岁月,count 函数是反正在咸集函数那一类的,便是 avg、sum 等,count 函数和这些反正在一道,注明它也是一个咸集函数。

  既然是咸集函数,那末就必要对前往的了局集举办一行行的剖断,这里就触及到一个成绩,前往的了局是啥?咱们分歧来看:

  对付 select count(1) from user; 这个查问来讲,InnoDB 引擎会去找到一个最小的索引树去遍历(没必要然是主键索引),可是不会读取数据,而是读到一个叶子节点,就前往 1,终末将了局累加。

  对付 select count(id) from user; 这个查问来讲,InnoDB 引擎会遍历全面主键索引,而后读取 id 并前往,不外由于 id 是主键,就正在 B+ 树的叶子节点上,是以这个进程不会触及到随机 IO(并没必要要回外等操纵去数据页拿数据),功能也是 OK 的。

  对付 select count(username) from user; 这个查问来讲,InnoDB 引擎会遍历整张外做全外扫描,读取每一行的 username 字段并前往,倘使 username 正在界说岁月设备了 not null,那末直接统计 username 的个数;倘使 username 正在界说的岁月没有设备 not null,那末就先剖断一下 username 能否为空,而后再统计。

  终末再来讲说 select count(*) from user; ,这个 SQL 的特别之处正在于它被 MySQL 优化过,当 MySQL 看到 count(*) 就了然你是思统计总记载数,就会去找到一个最小的索引树去遍历,而后统计记载数。

  由于主键索引(集结索引)的叶子节点是数据,而广泛索引的叶子节点则是主键值,是以广泛索引的索引树要小少许。但是正在上文的案例中,咱们唯有主键索引,是以终极运用的便是主键索引。

  现正在,倘使我篡改下面的外,为 username 字段也增加索引,而后咱们再来看 explain select count(*) from user; 的施行预备:

  

  可能看到,此时运用的索引便是 username 索引了,和咱们后面的说明了局是一律的。

  从下面的描摹中咱们便可能看出,第一个查问功能最高,第二个次之(由于必要读取 id 并前往),第三个最差(由于必要全外扫描),第四个的查问功能则贴近第一个。

   4. MyISAM 呢?

  大概有小搭档了然,MyISAM 引擎中的 select count(*) from user; 操纵施行起来利害常疾的,那是由于 MyISAM 把外中的行数直接存正在磁盘中了,必要的岁月直接读掏出来就好了,是以非凡疾。

  MyISAM 引擎之是以云云做,要紧是由于它是不救援工作的,是以它的统计本质上就非凡轻易,增加一行记载一行就好了。

  而咱们常用的 InnoDB 却不克不及云云做!为啥?由于 InnoDB 救援工作!为了救援工作,InnoDB 引入了 MVCC 众版本并发掌握,是以正在数据读取的岁月大概会有脏读、幻读以及不成反复读等成绩,详细可能参考 https://www.bilibili.com/video/BV14L4y1B7mB 视频。

  是以,InnoDB 必要将每一行数据拿出来,剖断该行数据对以后会话能否可睹,倘使可睹,就统计该行数据,不然不予统计。

  固然,MySQL 中的 MVCC 其实是一个非凡浩大的话题,松哥自此有空了再和大众细致先容 MVCC。

  好啦,现正在小搭档们懂了吧?有成绩接待留言接洽。

文章推荐:

nba2k18传奇版

cba2k巨星时刻

nba2k11没声音

大赢家篮球比分