MySQL中的全表扫描和索引树扫描 的实例详解
作者:Garrett_Wale 发布时间:2024-01-24 02:39:43
引言
在学习mysql时,我们经常会使用explain来查看sql查询的索引等优化手段的使用情况。在使用explain时,我们可以观察到,explain的输出有一个很关键的列,它就是type
属性,type表示的是扫描方式,代表 MySQL 使用了哪种索引类型,不同的索引类型的查询效率是不一样的。
在type这一列,有如下一些可能的选项:
system:系统表,少量数据,往往不需要进行磁盘IOconst:常量连接eq_ref:主键索引(primary key)或者非空唯一索引(unique not null)等值扫描ref:非主键非唯一索引等值扫描range:范围扫描index:索引树扫描ALL:全表扫描(full table scan)
在上面列出的7种选项中,前面五种我就不详细讲了,可以参考Mysql Explain之type详解这篇文章。我当时对于前五种属性是比较容易就理解了的,但是对于后面两种即索引树扫描和全表扫描我还是存在一些疑问。
索引树扫描我们是比较熟悉的,它就是会遍历聚簇索引树,底层是一颗B+树,叶子节点存储了所有的实际行数据。其实,全表扫描也是扫描的聚簇索引树,因为聚簇索引树的叶子节点中存储的就是实际数据,只要扫描遍历聚簇索引树就可以得到全表的数据了。
那索引树扫描和全表扫描究竟有什么区别呢?
以下将以一个实例来详细分析这两种扫描方式的区别。
实例
我们建立一张t_article
表:
create table t_article(
t_article_id int primary key auto_increment,
t_title varchar(40),
);
在我们创建的t_article
表中,只有两个字段,一个是主键t_article_id
,另一个是普通字段t_title
。
我们知道,InnoDB会将聚簇索引默认建立在主键上,而聚簇索引树中的叶子节点就存储了整张表的行数据。
接着,我们分别设计两个sql查询case:
走主键索引
explain SELECT t_article_id FROM t_article;
走全表扫描:
explain SELECT t_title FROM t_article;
以上两个查询都没有where查询,按理来说底层的sql执行情况应该是差不多的。
结果分析
我们可以来看看上面两种查询的结果,在查询时使用explain语句输出sql执行的详细信息。
1.走索引扫描
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | t_article | index | PRIMARY | 4 | 2 | 100 | Using index |
2.走全表扫描
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | t_article | ALL |
从以上两个查询结果中我们可以发现,走主键索引的查询和走全表的查询是不一样的。我们前面也提到了,InnoDB的索引是使用B+树来实现的,而主键索引中存储了整张表的数据,那全表扫描时其实也是扫描的主键索引。那为什么这两种查询会不一样呢?按理来说都是查询的主键索引,它们应该是一样的。
其实,它们两者是有一些细节区别的。
比如,第一个查询,它的优化手段是使用索引树扫描,也就是type中显示的index属性,而且它还使用了覆盖索引,即Extra列中的Using index属性。之所以第一个查询能够使用这两种优化手段,其实是因为select查询的结果列只包含主键,而主键的值是可以直接在遍历聚簇索引树时确定,也不需要回表查询了。
对于第二个查询,它也没有使用where进行过滤,而且它的select结果列包含的是普通列,并不是主键或者其他索引列,所以它会走全表扫描。而全表扫描其实底层也是扫描的聚簇索引树,也就是底层的B+树。这种全表扫描与索引树扫描有一个明显区别,那就是,全表扫描不仅仅需要扫描索引列,还需要扫描每个索引列中指向的实际数据,这里包含了所有的非索引列数据。
前面的分析可能还是有点生硬和难以理解,具体地,我们通过下面一张图来更直观地看一下:
图片源自:从数据页的角度看 B+ 树
从上面的图我们可以看到,对于索引扫描来讲,它只需要读取叶子节点的所有key,也就是索引的键,而不需要读取具体的data行数据;而对于全表扫描来说,它无法仅仅通过读取索引列获得需要的数据,还需要读取具体的data数据才能获取select中指定的非索引列的具体值。所以,全表扫描的效率相比于索引树扫描相对较低一点,但是差距不是很大。
参考
【mysql】全表扫描过程 & 聚簇索引 区别和联系
从数据页的角度看 B+ 树
来源:https://www.cnblogs.com/GarrettWale/p/16271622.html


猜你喜欢
- 什么是JSON Web Token?JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式
- 一、集中式vs分布式1.Subversion属于集中式的版本控制系统集中式的版本控制系统都有一个单一的集中管理的服务器,保存所有文件的修订版
- re.findall()方法及re.compile()re.findall()在字符串中找到正则表达式所匹配的所有子串,并返回一个列表;如果
- 基础知识-----黄金分割法960px宽度的网格设计的好处无需我多说了,下面主要是复习一下如何作图求出960px宽度下的黄金分割点1、首先沿
- 本文实例为大家分享了readAsDataUrl方法预览图片的具体代码,供大家参考,具体内容如下<html> <head&
- 网页采用了 UTF-8 编码格式,这本来没有问题,问题是外部 CSS 文件默认是 ANSI
- 业务需求我们需要一个微信小程序码,但是是需要提供给别人扫码的但是只有一个纯粹的小程序码是不好看的,所以需要推广的海报图片。再结合文字最终效果
- MyBatis 如何写配置文件和简单使用MyBatis3.x这里简单贴一下MyBatis的介绍,具体使用方法会在代码中贴出。MyBatis的
- 如果我们想对一个表的每一行做出比较复杂的操作,大多会想到用游标,本文中,我们将换一种思路,用SQL Server 2005中的新函数ROW_
- 在使用matplotlib模块时画坐标图时,往往需要对坐标轴设置很多参数,这些参数包括横纵坐标轴范围、坐标轴刻度大小、坐标轴名称等 在mat
- mysql 5.5 安装配置方法图文教程回忆一下mysql 5.5 安装配置方法,整理mysql 5.5 安装配置教程笔记,分享给大家。My
- 该平台会集成UI自动化及api自动化,里面也会涉及到一些简单的HTML等前端,当然都是很基础的东西。在以后的博客里,我会一点点的尽量写详细,
- 一、项目说明在日常生活中,我们经常会存取一些朋友们的丑照,在这个项目中,我们以萌萌哒的熊猫头作为背景,然后试着在背景图上加入朋友们的照片。效
- 本文要实现的功能是:根据下拉列表的选项将数据库中对应的内容显示在页面,选定要排除的选项后,提交剩余的选项到数据库。为了方便前后台交互,利用了
- 问题描述: 有2个数组如下a = [3,3,3,4,4,4,5,6,7]b = [3,3,4,4]第1题:从数组a中删除所有在数组b中出现过
- ./runInstaller 启动图形化报错 PRVF-0002 : Could not retrieve local nodename.
- $str=preg_replace("/\s+/", " ", $str); //过滤多余回车 $s
- 数据库事务-锁机制1.什么是锁锁,其实就是一个内存种的结构,在事务还没有来之前是没有锁存在的。在事务未开始前只有一条记录,是没有锁和记录之间
- SQLServer中有五种约束,Primary Key约束、Foreign Key约束、Unique约束、Default约束和Check约束
- 实验环境1.安装Python 3.72.安装requests, bs4,pymysql 模块实验步骤1.安装环境及模块可参考https://