1226关于count(*)不走主键索引反而走二级索引
转自 http://www.2cto.com/database/201508/433975.html
- mysqlcount(*)会选哪个索引?
-
今天在查询一个表行数的时候,发现count(1)和count(*)执行效率居然是一样的。这跟Oracle还是有区别的。遂查看两种方式的执行计划:
123456789101112131415161718mysql>
select
count
(1)
from
customer;
+
----------+
|
count
(1) |
+
----------+
| 150000 |
+
----------+
1 row
in
set
(0.03 sec)
mysql> flush tables;
Query OK, 0
rows
affected (0.00 sec)
mysql>
select
count
(*)
from
customer;
+
----------+
|
count
(*) |
+
----------+
| 150000 |
+
----------+
1 row
in
set
(0.03 sec)
查看执行计划:
123456789101112131415161718192021222324mysql> explain
select
count
(1)
from
customer;
+
----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+
| id | select_type |
table
| type | possible_keys |
key
| key_len | ref |
rows
| Extra |
+
----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+
| 1 | SIMPLE | customer |
index
|
NULL
| i_c_nationkey | 5 |
NULL
| 151191 | Using
index
|
+
----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+
1 row
in
set
(0.00 sec)
mysql> explain
select
count
(*)
from
customer;
+
----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+
| id | select_type |
table
| type | possible_keys |
key
| key_len | ref |
rows
| Extra |
+
----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+
| 1 | SIMPLE | customer |
index
|
NULL
| i_c_nationkey | 5 |
NULL
| 151191 | Using
index
|
+
----+-------------+----------+-------+---------------+---------------+---------+------+--------+-------------+
1 row
in
set
(0.00 sec)
mysql> show
index
from
customer;
+
----------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
|
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 | | |
+
----------+------------+---------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2
rows
in
set
(0.08 sec)
发现不管是count(1)或count(*)都是走的i_c_nationkey这个索引。平时我们检索数据的时候肯定是主键索引效率高,那么我们强制主键索引来看看:
1234567891011121314mysql>
select
count
(*)
from
customer
force
index
(
PRIMARY
);
+
----------+
|
count
(*) |
+
----------+
| 150000 |
+
----------+
1 row
in
set
(0.68 sec)
mysql> explain
select
count
(*)
from
customer
force
index
(
PRIMARY
);
+
----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
| id | select_type |
table
| type | possible_keys |
key
| key_len | ref |
rows
| Extra |
+
----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | customer |
index
|
NULL
|
PRIMARY
| 4 |
NULL
| 150525 | Using
index
|
+
----+-------------+----------+-------+---------------+---------+---------+------+--------+-------------+
1 row
in
set
(0.00 sec)
可以看到走主键索引的时候效率比较差。那么是为什么呢。
平时我们检索一列的时候,基本上等值或范围查询,那么索引基数大的索引必然效率很高。但是在做count(*)的时候并没有检索具体的一行或者一个范围。那么选择基数小的索引对
count操作效率会更高。在做count操作的时候,mysql会遍历每个叶子节点,所以基数越小,效率越高。mysql非聚簇索引叶子节点保存的主键ID,所以需要检索两遍索引。但是这里相对于遍历主键索引。及时检索两遍索引效率也比单纯的检索主键索引快。
那么再以一个表作为证明:1234567891011121314151617181920212223242526mysql> explain
select
count
(*)
from
lineitem;
+
----+-------------+----------+-------+---------------+--------------+---------+------+---------+-------------+
| id | select_type |
table
| type | possible_keys |
key
| key_len | ref |
rows
| Extra |
+
----+-------------+----------+-------+---------------+--------------+---------+------+---------+-------------+
| 1 | SIMPLE | lineitem |
index
|
NULL
| i_l_shipdate | 4 |
NULL
| 6008735 | Using
index
|
+
----+-------------+----------+-------+---------------+--------------+---------+------+---------+-------------+
1 row
in
set
(0.00 sec)
mysql> show
index
from
lineitem;
+
----------+------------+-----------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
|
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 | | |
+
----------+------------+-----------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
12
rows
in
set
(0.96 sec)
这里一看l_shipDATE并不是基数最小的呀,殊不知这个统计信息是不准确的。我们用sql看一下。
1234567mysql>
select
count
(
distinct
(l_shipDATE))
from
lineitem;
+
-----------------------------+
|
count
(
distinct
(l_shipDATE)) |
+
-----------------------------+
| 2526 |
+
-----------------------------+
1 row
in
set
(0.01 sec)
那么比他小的那些列呢?
1234567mysql>
select
count
(
distinct
(l_receiptDATE))
from
lineitem;
+
--------------------------------+
|
count
(
distinct
(l_receiptDATE)) |
+
--------------------------------+
| 2554 |
+
--------------------------------+
1 row
in
set
(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) 能够唯一标识表中某一行的属性或属性组.一个表只能有一个主键,但可以有多个候选索引.主键常常与外键构成参照完整性约束,防止出现数据不一致.主键可以保证记录的唯一和 ...
随机推荐
- 4.在MVC中使用仓储模式进行增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-using-the-repository-pattern-in-mvc/ 系列目录: ...
- 【无私分享:ASP.NET CORE 项目实战(第七章)】文件操作 FileHelper
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 在程序设计中,我们很多情况下,会用到对文件的操作,在 上一个系列 中,我们有很多文件基本操作的示例,在Core中有一些改变,主 ...
- Android ORM -- Litepal(1)
ORM,即Object Relation Mapping,对象关系映射,实现了程序里面的类和数据库里面的数据之间的对应关系,对数据库的操作可以通过对类的操作去实现,不用再写SQL语句,从而提高了开发效 ...
- 来玩Play框架04 表单
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 表单(form)是最常见的从客户往服务器传递数据的方式.Play框架提供了一些工具 ...
- python入门-python解释器执行
最近由于公司需要,接触了python这门神奇的语言,给我的感觉就是开发快速和代码简洁. 开始还是先罗列一下解释性语言和编译性语言的差别吧0.0! 编译性语言:是在程序运行前,需要专门的一个编译过程 ...
- jdk jre jvm 三者之间关系
JDK JDK是java开发工具包,是Sun公司针对Java开发员的产品. JDK 中包含JRE,在JDK安装的目录下有一个叫jre的目录,里面有两个文件夹,bin/和lib,其中bin就是j ...
- js数组转换问题
一维数组转多维数组 var arr=[1,2,3,4,5,6,7,8,9,10]; function splitArray(arr,size){ var result = []; var tempAr ...
- 十种MYSQL显错注入原理讲解(一)
开篇我要说下,在<代码审计:企业级Web代码安全架构>这本书中讲十种MYSQL显错注入,讲的很清楚. 感兴趣请去读完,若处于某种原因没读还想了解,那请继续往下. 1.count,rand, ...
- Java之this关键字的用法
Java 中的 this 关键字指当前的对象,可以直接用其调用当前对象的成员变量,也可以直接用其调用当前对象的成员方法,这是我们常见的场景,那么有没有其它的情况呢! this 还可以在无参的构造方法中 ...
- 华为Java编程军规,每季度代码验收标准
引言: 这个标准是衡量代码本身的缺陷,也是衡量一个研发人员本身的价值. 军规一:[避免在程序中使用魔鬼数字,必须用有意义的常量来标识.] 军规二:[明确方法的功能,一个方法仅完成一个功能.] 军规三: ...