如何避免mysql回表查询_mysql如何避免回表查询
《迅猛定位低效SQL?》留了一个尾巴:
select id,name where name=‘shenjian‘
select id,name,sexwhere name=‘shenjian‘
多查询了一个属性,为何检索过程完全不同?
什么是回表查询?
什么是索引覆盖?
如何实现索引覆盖?
哪些场景,可以利用索引覆盖来优化SQL?
这些,这是今天要分享的内容。
画外音:本文试验基于MySQL5.6-InnoDB。
一、什么是回表查询?
这先要从InnoDB的索引实现说起,InnoDB有两大类索引:
聚集索引(clustered index)
普通索引(secondary index)
InnoDB聚集索引和普通索引有什么差异?
InnoDB聚集索引的叶子节点存储行记录,因此, InnoDB必须要有,且只有一个聚集索引:
(1)如果表定义了PK,则PK就是聚集索引;
(2)如果表没有定义PK,则第一个not NULL unique列是聚集索引;
(3)否则,InnoDB会创建一个隐藏的row-id作为聚集索引;
画外音:所以PK查询非常快,直接定位行记录。
InnoDB普通索引的叶子节点存储主键值。
画外音:注意,不是存储行记录头指针,MyISAM的索引叶子节点存储记录指针。
举个栗子,不妨设有表:
t(id PK, name KEY, sex, flag);
画外音:id是聚集索引,name是普通索引。
表中有四条记录:
1, shenjian, m, A
3, zhangsan, m, A
5, lisi, m, A
9, wangwu, f, B
两个B+树索引分别如上图:
(1)id为PK,聚集索引,叶子节点存储行记录;
(2)name为KEY,普通索引,叶子节点存储PK值,即id;
既然从普通索引无法直接定位行记录,那普通索引的查询过程是怎么样的呢?
通常情况下,需要扫码两遍索引树。
例如:
select * from t where name=‘lisi‘;
是如何执行的呢?
如粉红色路径,需要扫码两遍索引树:
(1)先通过普通索引定位到主键值id=5;
(2)在通过聚集索引定位到行记录;
这就是所谓的回表查询,先定位主键值,再定位行记录,它的性能较扫一遍索引树更低。
二、什么是索引覆盖(Covering index)?
额,楼主并没有在MySQL的官网找到这个概念。
画外音:治学严谨吧?
借用一下SQL-Server官网的说法。
MySQL官网,类似的说法出现在explain查询计划优化章节,即explain的输出结果Extra字段为Using index时,能够触发索引覆盖。
不管是SQL-Server官网,还是MySQL官网,都表达了:只需要在一棵索引树上就能获取SQL所需的所有列数据,无需回表,速度更快。
三、如何实现索引覆盖?
常见的方法是:将被查询的字段,建立到联合索引里去。
仍是《迅猛定位低效SQL?》中的例子:
create table user (
id int primary key,
name varchar(20),
sex varchar(5),
index(name)
)engine=innodb;
第一个SQL语句:
select id,name from user where name=‘shenjian‘;
能够命中name索引,索引叶子节点存储了主键id,通过name的索引树即可获取id和name,无需回表,符合索引覆盖,效率较高。
画外音,Extra:Using index。
第二个SQL语句:
select id,name,sexfrom user where name=‘shenjian‘;
能够命中name索引,索引叶子节点存储了主键id,但sex字段必须回表查询才能获取到,不符合索引覆盖,需要再次通过id值扫码聚集索引获取sex字段,效率会降低。
画外音,Extra:Using index condition。
如果把(name)单列索引升级为联合索引(name, sex)就不同了。
create table user (
id int primary key,
name varchar(20),
sex varchar(5),
index(name, sex)
)engine=innodb;
可以看到:
select id,name … where name=‘shenjian‘;
select id,name,sex… where name=‘shenjian‘;
都能够命中索引覆盖,无需回表。
画外音,Extra:Using index。
四、哪些场景可以利用索引覆盖来优化SQL?
场景1:全表count查询优化
原表为:
user(PK id, name, sex);
直接:
select count(name) from user;
不能利用索引覆盖。
添加索引:
alter table user add key(name);
就能够利用索引覆盖提效。
场景2:列查询回表优化
select id,name,sex … where name=‘shenjian‘;
这个例子不再赘述,将单列索引(name)升级为联合索引(name, sex),即可避免回表。
场景3:分页查询
select id,name,sex …order byname limit 500,100;
将单列索引(name)升级为联合索引(name, sex),也可以避免回表。
转载:https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651962609&idx=1&sn=46e59691257188d33a91648640bcffa5&chksm=bd2d092d8a5a803baea59510259b28f0669dbb72b6a5e90a465205e9497e5173d13e3bb51b19&mpshare=1&scene=1&srcid=&sharer_sharetime=1564396837343&sharer_shareid=7cd5f6d8b77d171f90b241828891a85f&key=abd60b96b5d1f2e52ca45314fb2c95a67fad7a457fe265562eb51a1c026389d3f28c52359f96e920368ab44a5d08ebcbbe2ded474be2ba70731ed8b5dcc5dd68cc0eceb4989a74fb04e5055c78af8d38&ascene=1&uin=MTAwMjA4NTM0Mw%3D%3D&devicetype=Windows+7&version=62060739&lang=zh_CN&pass_ticket=tXA4xc7SZYamLpGZz5B6JwJa1ZRvZ4bRlmzFhXwEKeOfloPLulU0O80gsIQUiONb
mysql如何避免回表查询
如何避免mysql回表查询_mysql如何避免回表查询相关推荐
- mysql 回表查询优化_MySQL中的回表查询与索引覆盖:一次百万级别分页查询使用Limit 从90秒到0.6毫秒的优化...
这里写目录标题 事故现场 解决方案 提到的"回表查询" InnoDB的索引 什么是回表查询 怎么优化回表查询 事故现场 数据库使用的MySQL,有一个日志表,需要进行分页查询,于是 ...
- mysql 左关联查询_MySQL 左关联右表条件查询
MySQL的新知识: 之前数据库没学好,不知道LEFT JOIN ON后边可以加条件 首先业务是有个A表,然后会依据A表信息来在B表生成一条对应数据, 操作时候展示A表数据,如果B表已经有对应数据,显 ...
- mysql同张表关联多次查询_MySQL多次单表查询和多表联合查询
Tip:不建议执行三张表以上的多表联合查询 对数据量不大的应用来说,多表联合查询开发高效,但是多表联合查询在表数据量大,并且没有索引的时候,如果进行笛卡儿积,那数据量会非常大,sql执行效率会非常低 ...
- mysql 多个select查询_MySQL的select多表查询
select 语句: select 语句一般用法为: select 字段名 from tb_name where 条件 ; select 查询语句类型一般分为三种: 单表查询,多表查询,子查询 最简单 ...
- mysql 分表索引_mysql中,分表查询和索引查询哪个更快?
谢谢邀请! 查询快慢主决的因素有很多,存储碎片.数据量大属于I/O类问题:表结构设计.查询语句属于技术是否熟练(经验)问题.对于你的分表快还是索引快的这个问题本身就是有问题的: 在建立数据表的时候,索 ...
- mysql 慢查询_mysql如何捕捉慢日志查询
慢日志查询日志 查询超过变量 long_query_time指定时间值的为慢查询,但是查询获取锁(包括锁等待)的时间不计入查询时间内,mysql 记录慢查询日志是在查询执行完毕且已经完全释放锁之后才记 ...
- mysql分区和分表比较_MySQL分区和分表的区别与联系
一.分区和分表简介 分表 就是将一张大表分成N个小表. 分区 将一张大表的数据分成N个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上. 二.分区和分表的区别 1. 实现方式 1.1 分表 My ...
- mysql约束建表规范_MySQL 建库建表规范
1.约束 1.PrimaryKey(PK)主键 特点:唯一 + 非空,一张表中只能有一个主键约束,一般是一个数字列,最好是无意义的. 2.NOT NULL 非空 特点:不能为空,建议在MySQL中,业 ...
- mysql 索引查询_mysql索引的建立和查询语句优化
首先表内容展示: # 300W条的模拟数据 # 并且没有建立任何索引 不建立索引的查询时间: 以id查询的(4秒多): 以email查询的(4秒多): 建立主键索引后: alter table s1 ...
- mysql查看执行计划_MySql中如何使用 explain 查询 SQL 的执行计划
explain命令是查看查询优化器如何决定执行查询的主要方法. 这个功能有局限性,并不总会说出真相,但它的输出是可以获取的最好信息,值得花时间去了解,因为可以学习到查询是如何执行的. 1.什么是MyS ...
最新文章
- MIT研究发现:十大最常用数据集标签错误率达3.4%
- 原来,07年我把自己给和谐了
- 【转】对服务采购订单的条目确认
- Hadoop报错:All specified directories are failed to load.
- Angularjs1.x 中的 service,factory,provider,constant,value
- 2016重庆计算机一级考试题型,重庆计算机一级考试真题2016年最新(笔试+上机).doc...
- LeetCode MySQL 185. 部门工资前三高的所有员工(dense_rank)
- ASP.NET企业开发框架IsLine FrameWork系列之六--DataProvider 数据访问(下)
- 论高校计算机信息管理能力的提升,论高校计算机信息管理能力的提升
- 51Nod - 1051(思维)
- 求1+2+3+...+n(剑指 Offer 64)
- 元数据是什么?举例告诉你什么是元数据
- C语言实现动态通讯录(附带文件保存)
- 金融计算器,python实现
- 【ipad 作为 mac 分屏分辨率调整 | sidercar 分辨率调整】
- 安全狗获聘福建省网络与信息安全信息通报中心技术支撑单位
- LIBSVM (三) 葡萄酒种类识别
- Python 将excel中的选择题 导入到word文档中
- Spring MVC框架概述
- android11适配机型,AndroidP首批适配机型有哪些?这11款可尝鲜
热门文章
- Attribute “singleton” must be declared for element type “bean”.
- Error: docker-ce conflicts with 2:docker-1.13.1-208.git7d71120.el7_9.x86_64
- 查询字段是date类型的数据
- Linux Shell脚本专栏_批量创建100用户并设置密码脚本_03
- 蓝牙打印和网口打印的实现
- 编写一个C程序,实现以下功能:编写一个函数decTobin(int n),该函数能将一个十进制数n转换成二进制数,输入13 输出 1101。在main函数中输入整数n,调用函数,输出它的二进制
- js数组查找最接近_在JavaScript数组中找到最小元素的位置
- 数据 正则化 python_python3.6怎么单独正则化/标准化DataFrame中的指定列数据
- 计算机房地板厚度,机房防静电地板 架空地板的技术参数与地板规格种类
- C语言 *p++/*(p)++/*(p++)/*p++ - C语言零基础入门教程