1226关于count(*)不走主键索引反而走二级索引
转自 http://www.2cto.com/database/201508/433975.html
- mysqlcount(*)会选哪个索引?
-
今天在查询一个表行数的时候,发现count(1)和count(*)执行效率居然是一样的。这跟Oracle还是有区别的。遂查看两种方式的执行计划:
123456789101112131415161718mysql>selectcount(1)fromcustomer;+----------+|count(1) |+----------+| 150000 |+----------+1 rowinset(0.03 sec)mysql> flush tables;Query OK, 0rowsaffected (0.00 sec)mysql>selectcount(*)fromcustomer;+----------+|count(*) |+----------+| 150000 |+----------+1 rowinset(0.03 sec)查看执行计划:
123456789101112131415161718192021222324mysql> explainselectcount(1)fromcustomer;+----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+| id | select_type |table| type | possible_keys |key| key_len | ref |rows| Extra |+----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+| 1 | SIMPLE | customer |index|NULL| i_c_nationkey | 5 |NULL| 151191 | Usingindex|+----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+1 rowinset(0.00 sec)mysql> explainselectcount(*)fromcustomer;+----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+| id | select_type |table| type | possible_keys |key| key_len | ref |rows| Extra |+----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+| 1 | SIMPLE | customer |index|NULL| i_c_nationkey | 5 |NULL| 151191 | Usingindex|+----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+1 rowinset(0.00 sec)mysql> showindexfromcustomer;+----------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+|Table| Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed |Null| Index_type | Comment | Index_comment |+----------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+| customer | 0 |PRIMARY| 1 | c_custkey | A | 150525 |NULL|NULL| | BTREE | | || customer | 1 | i_c_nationkey | 1 | c_nationkey | A | 47 |NULL|NULL| YES | BTREE | | |+----------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+2rowsinset(0.08 sec)发现不管是count(1)或count(*)都是走的i_c_nationkey这个索引。平时我们检索数据的时候肯定是主键索引效率高,那么我们强制主键索引来看看:
1234567891011121314mysql>selectcount(*)fromcustomerforceindex(PRIMARY);+----------+|count(*) |+----------+| 150000 |+----------+1 rowinset(0.68 sec)mysql> explainselectcount(*)fromcustomerforceindex(PRIMARY);+----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+| id | select_type |table| type | possible_keys |key| key_len | ref |rows| Extra |+----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+| 1 | SIMPLE | customer |index|NULL|PRIMARY| 4 |NULL| 150525 | Usingindex|+----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+1 rowinset(0.00 sec)可以看到走主键索引的时候效率比较差。那么是为什么呢。
平时我们检索一列的时候,基本上等值或范围查询,那么索引基数大的索引必然效率很高。但是在做count(*)的时候并没有检索具体的一行或者一个范围。那么选择基数小的索引对
count操作效率会更高。在做count操作的时候,mysql会遍历每个叶子节点,所以基数越小,效率越高。mysql非聚簇索引叶子节点保存的主键ID,所以需要检索两遍索引。但是这里相对于遍历主键索引。及时检索两遍索引效率也比单纯的检索主键索引快。
那么再以一个表作为证明:1234567891011121314151617181920212223242526mysql> explainselectcount(*)fromlineitem;+----+-------------+----------+-------+---------------+--------------+---------+------+---------+-------------+| id | select_type |table| type | possible_keys |key| key_len | ref |rows| Extra |+----+-------------+----------+-------+---------------+--------------+---------+------+---------+-------------+| 1 | SIMPLE | lineitem |index|NULL| i_l_shipdate | 4 |NULL| 6008735 | Usingindex|+----+-------------+----------+-------+---------------+--------------+---------+------+---------+-------------+1 rowinset(0.00 sec)mysql> showindexfromlineitem;+----------+------------+-----------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+|Table| Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed |Null| Index_type | Comment | Index_comment |+----------+------------+-----------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+| lineitem | 0 |PRIMARY| 1 | l_orderkey | A | 2997339 |NULL|NULL| | BTREE | | || lineitem | 0 |PRIMARY| 2 | l_linenumber | A | 5994679 |NULL|NULL| | BTREE | | || lineitem | 1 | i_l_shipdate | 1 | l_shipDATE | A | 5208 |NULL|NULL| YES | BTREE | | || lineitem | 1 | i_l_suppkey_partkey | 1 | l_partkey | A | 428191 |NULL|NULL| YES | BTREE | | || lineitem | 1 | i_l_suppkey_partkey | 2 | l_suppkey | A | 1998226 |NULL|NULL| YES | BTREE | | || lineitem | 1 | i_l_partkey | 1 | l_partkey | A | 461129 |NULL|NULL| YES | BTREE | | || lineitem | 1 | i_l_suppkey | 1 | l_suppkey | A | 19213 |NULL|NULL| YES | BTREE | | || lineitem | 1 | i_l_receiptdate | 1 | l_receiptDATE | A | 17 |NULL|NULL| YES | BTREE | | || lineitem | 1 | i_l_orderkey | 1 | l_orderkey | A | 2997339 |NULL|NULL| | BTREE | | || lineitem | 1 | i_l_orderkey_quantity | 1 | l_orderkey | A | 1998226 |NULL|NULL| | BTREE | | || lineitem | 1 | i_l_orderkey_quantity | 2 | l_quantity | A | 5994679 |NULL|NULL| YES | BTREE | | || lineitem | 1 | i_l_commitdate | 1 | l_commitDATE | A | 7836 |NULL|NULL| YES | BTREE | | |+----------+------------+-----------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+12rowsinset(0.96 sec)这里一看l_shipDATE并不是基数最小的呀,殊不知这个统计信息是不准确的。我们用sql看一下。
1234567mysql>selectcount(distinct(l_shipDATE))fromlineitem;+-----------------------------+|count(distinct(l_shipDATE)) |+-----------------------------+| 2526 |+-----------------------------+1 rowinset(0.01 sec)那么比他小的那些列呢?
1234567mysql>selectcount(distinct(l_receiptDATE))fromlineitem;+--------------------------------+|count(distinct(l_receiptDATE)) |+--------------------------------+| 2554 |+--------------------------------+1 rowinset(0.01 sec)其他就不看了,这里再次说明mysql选择了基数小的索引。
1226关于count(*)不走主键索引反而走二级索引的更多相关文章
- mysql InnoDB index 主键采用聚簇索引,二级索引不采用聚簇索引
原文链接 我的归纳: (1)InnoDB的主键采用聚簇索引存储,使用的是B+Tree作为索引结构,但是叶子节点存储的是索引值和数据本身(注意和MyISAM的不同). (2)InnoDB的二级索引不使用 ...
- 【mysql优化】mysql count(*)、count(1)、count(主键字段)、count(非主键字段)哪个性能最佳
测试结果为:count(*)和count(1)基本相等,count(非主键字段)最耗性能 -- 数据量 708254select count(*) from tmp_test1;-- avg 0.22 ...
- Oracle删除主键约束的同时删除索引
继续昨天的折腾(Oracle修改主键约束),删掉主键约束后,发现唯一索引并未删掉.仔细看了下,主键约束跟唯一索引名称不一样,这说明是先创建了唯一索引,后创建的主键约束.我们来试验下: SQL> ...
- 主键primary key和唯一索引unique index
1)主键一定是唯一性索引,唯一性索引并不一定就是主键. 2)主键就是能够唯一标识表中某一行的属性或属性组,一个表只能有一个主键,但可以有多个候选索引. 3)主键常常与外键构成参照完整性约束,防止出现数 ...
- mysql 主键和默认 设为索引的规则
一.mysql 表中如果是单主键的话,那这个主键也会被 系统默认建为 索引 二.mysql 表中如果是复合主键的话,那系统会遵循左对齐原则,即如复合主键 a 和 b字段和c字段..., 默认建的主键索 ...
- MySQL 聚簇索引&&二级索引&&辅助索引
MySQL非聚簇索引&&二级索引&&辅助索引 mysql中每个表都有一个聚簇索引(clustered index ),除此之外的表上的每个非聚簇索引都是二级索引,又叫辅 ...
- COUNT(*)、COUNT(主键)、COUNT(1)
MyISAM引擎,记录数是结构的一部分,已存cache在内存中; InnoDB引擎,需要重新计算,id是主键的话,会加快扫描速度: 所以select count(*) MyISAM完胜! MyISA ...
- 图解MySQL:count(*) 、count(1) 、count(主键字段)、count(字段)哪个性能最好?
大家好,我是小林. 当我们对一张数据表中的记录进行统计的时候,习惯都会使用 count 函数来统计,但是 count 函数传入的参数有很多种,比如 count(1).count(*).count(字段 ...
- MySQL的几个概念:主键,外键,索引,唯一索引
概念: 主键(primary key) 能够唯一标识表中某一行的属性或属性组.一个表只能有一个主键,但可以有多个候选索引.主键常常与外键构成参照完整性约束,防止出现数据不一致.主键可以保证记录的唯一和 ...
随机推荐
- 在node.js中,使用基于ORM架构的Sequelize,操作mysql数据库之增删改查
Sequelize是一个基于promise的关系型数据库ORM框架,这个库完全采用JavaScript开发并且能够用在Node.JS环境中,易于使用,支持多SQL方言(dialect),.它当前支持M ...
- php中实现的一个curl批处理的实例
curl是利用URL语法在命令行方式下工作的开源文件传输工具 本文在php中实现了的一个curl批处理的实例. 代码如下: header("Content-Type:text/html;ch ...
- 遭遇Web print
一直都知道Web打印还不太成熟,以前IE横行时,普遍都是采用打印相关的ActiveX控件,有些国产厂家做得不错,只是那时还没有付费能力,没有太多关注.而纯粹基于Web标准的打印,浏览器对CSS pri ...
- 如何实现一个php框架系列文章【5】安全处理输入
所有的外部输入参数都应该检查合法性. 未正确处理输入数据将可能导致sql注入等漏洞. 框架提供系列函数来取$_REQUEST中的值 requestInt requestString requestFl ...
- 5分钟创建一个SpringBoot + Themeleaf的HelloWord应用
第一步:用IDE创建一个普通maven工程,我用的eclipse. 第二步:修改pom.xml,加入支持SpringBoot和Themeleaf的依赖,文件内容如下: <?xml version ...
- entityframework学习笔记--007-实体数据建模基础之继承关系映射TPT
Table per Type Inheritance (TPT)建模 1.假设你有两张表与一张公共的表密切相关,如图7-1所示,Businiss表与eCommerce表.Retail表有1:0...1 ...
- JHipster框架的简要搭建与说明
JHipster的亮点 风头超劲,席卷欧美,最新全能Java Web开发程式产生器 (java web generator). 由Java专家累积的开发经验,配上各类实用的框架技术,去繁取精的运用,全 ...
- ASP.NET中后台数据和前台控件的绑定
关于ASP.NET中后台数据库和前台的数据控件的绑定问题 最近一直在学习个知识点,自己创建了SQL Server数据库表,想在ASP.NET中连接数据库,并把数据库中的数据显示在前台,注意,这里的数据 ...
- 使用 Vue 2.0 实现服务端渲染的 HackerNews
Vue 2.0 支持服务端渲染 (SSR),并且是流式的,可以做组件级的缓存,这使得极速渲染成为可能.同时, 和 2.0 也都能够配合 SSR 提供同构路由和客户端 state hydration.v ...
- webpack 使用优化指南
前言 本文不是webpack入门文章,如果对webpack还不了解,请前往题叶的Webpack入门,或者阮老师的Webpack-Demos. 为什么要使用Webpack 与react一类模块化开发的框 ...
我要投稿