千万级数据库使用索引查询速度更慢的疑惑-数据回表问题
环境
数据库:TiDB数据库(和mysql数据库极其相似的数据库)
表名:index_basedata
表数据:13 000 000条数据
表索引:包含一个普通索引,索引列 ”year“
测试sql:
SQL1 : select brand from index_basedata where year = 2018 group by day limit 5;
SQL2 : select brand from index_basedata where month = 201807 group by day limit 5;
SQL3 : select brand from index_basedata where year = 2018 limit 5;
SQL4 : select brand from index_basedata where month = 201807 limit 5;
sql1与sql2对比 , sql3与sql4对比
问题
测试sql执行时间:
SQL1 : 23.6s
SQL2 : 4.5s
SQL3 : 0.007s
SQL4 : 1.4s
explain解释: 了解TiDB数据库相关与explain请移步:https://pingcap.com/docs-cn/overview/#tidb-%e6%95%b4%e4%bd%93%e6%9e%b6%e6%9e%84
sql1:select brand from xcar_index_basedata_noprice where year = 2018 group by day limit 5;
sql2:select brand from xcar_index_basedata_noprice where month = 201807 group by day limit 5;
sql3:select brand from xcar_index_basedata_noprice where year = 2018 limit 5;
sql4:select brand from xcar_index_basedata_noprice where month = 201807 limit 5;
从图中可以看出,sql1和sql3使用了索引,sql2和sql4没有使用索引。
对于sql1和sql2,本应该使用所以的查询时间少,但是使用了索引的sql1使用的时间是没有使用索引的sql2查询时间的5倍,为什么?
对于sql3和sql4,恢复了正常,使用索引比不使用索引查询速度快,为什么上述两个现象会相差如此之大?
解答(以下为个人理解,不同理解请不吝指教)
在sql1和sql2中,sql1索引列获取数据的速度大于sql2中获得数据的速度。但是在group by时在sql1中,使用索引得到的地址,需要回表才可以得到真实的数据,需要根据地址去获取数据,数据回表问题严重。
在sql2中获取的是直接数据,group by 不需要回表。
sql2,sql3,sql4表现正常。
什么是回表?
通俗的讲:如果索引的列在select所需获得列中就不需要回表(因为在mysql中索引是根据索引列的值进行排序的,所以索引节点中存在该列中的部分值),如果select所需获得列中有大量的非索引列,索引就需要到表中找到相应的列的信息,这就叫回表。
案例:
测试环境:与上述相同
测试sql:
sql1:select brand from index_basedata where year = 2018 group by day limit 5;
执行时间:21.8s
explain一下:
使用了索引“year”, 则索引列为year,但是select brand from..中brand并不是索引列,就需要回表(通过图也可以看出,进行了tablescan,另外其中的IndexLookUp也说明了进行了回表),所以花费时间长
sql2:select brand from index_basedata where year = 2018 group by year limit 5;
执行时间:21.7s
explain一下:
使用了索引“year”, 则索引列为year,但是select brand from..中brand并不是索引列,就需要回表(通过图也可以看出,进行了tablescan,另外其中的IndexLookUp也说明了进行了回表),所以花费时间长,另外,对于sql2中的group by使用的是索引列,所以使用的StreamAgg,不同于sql1
sql3:select year from index_basedata where year = 2018 group by year limit 5;
执行时间:2.5s
explain一下:
可以看到:没有tablescan,也没有使用IndexLookUp而是IndexReader说明直接从索引中读取索引列并使用。
总结:在上述案例中,sql3使用了索引列,没有进行回表,sql1与sql2进行了回表,所以花费时间长。所以说,发生严重的回表的时候,查询速度比不使用索引还慢。
那么,下面的5个sql执行时间能不能理解呢?
select year from xcar_index_basedata_noprice where year = 2018 group by year limit 5;
select month from xcar_index_basedata_noprice where month = 201807 group by month limit 5
select brand_id from xcar_index_basedata_noprice where month = 201807 group by month limit 5;
select brand_id from xcar_index_basedata_noprice where year = 2018 group by year limit 5;
select brand_id from xcar_index_basedata_noprice where year = 2018 group by month limit 5;
对应执行时间:
点击「文章最下方-Geek Tech」或搜索「Geek Tech」公众号可免费获取多种PDF技术文档:Java、shell、Git、算法、单元测试等PDF! 还有每天的技术文章推送和每月免费送书抽奖!
- 《一文教会你写90%的Shell脚本》PDF:发送消息“shell”
- 《Git常用操作和Git底层原理全集》PDF:发送消息“git”
- 《图解-图数据库系列合集》PDF:发送消息“图数据库”
- 《近百页数据库和sql基础知识整理》PDF:发送消息“数据库”
- HRM人事管理系统+经典飞机大战+像素鸟源码+:关注后发送消息“源码”
- 更多免费pdf和资源可关注公众号查看!
「点击下方公众号Tab栏关注我们,专注于程序员的技术公众号!」
千万级数据库使用索引查询速度更慢的疑惑-数据回表问题相关推荐
- python读取千万级数据库数据类型_解决python读取几千万行的大表内存问题
Python导数据的时候,需要在一个大表上读取很大的结果集. 如果用传统的方法,Python的内存会爆掉,传统的读取方式默认在内存里缓存下所有行然后再处理,内存容易溢出 解决的方法: 1)使用SSCu ...
- 如何实现mysql千万级数据库插入速度和读取速度
mysql千万级数据库插入速度和读取速度的调整记录 2018.11.1 Mysql version 5.7.23 一般情况下mysql上百万数据读取和插入更新是没什么问题了,但到了上千万级就会出现很慢 ...
- mysql数据库加载太慢_mysql千万级数据库插入速度和读取速度的调整记录
一般情况下mysql上百万数据读取和插入更新是没什么问题了,但到了上千万级就会出现很慢,下面我们来看mysql千万级数据库插入速度和读取速度的调整记录吧. (1)提高数据库插入性能中心思想:尽量将数据 ...
- mysql千万级数据库插入速度和读取速度的调整记录。
(1)提高数据库插入性能中心思想:尽量将数据一次性写入到Data File和减少数据库的checkpoint 操作.这次修改了下面四个配置项: 1)将 innodb_flush_l ...
- 整理:mysql千万级数据库插入速度和读取速度的调整
一 1:innodb_flush_log_at_trx_commit参数解释:1:log buffer将每秒一次地写入log file中,并且log file的flush(刷到磁盘)操作同时进行.该模 ...
- mysql 分表索引_mysql中,分表查询和索引查询哪个更快?
谢谢邀请! 查询快慢主决的因素有很多,存储碎片.数据量大属于I/O类问题:表结构设计.查询语句属于技术是否熟练(经验)问题.对于你的分表快还是索引快的这个问题本身就是有问题的: 在建立数据表的时候,索 ...
- 30多条mysql数据库优化方法,千万级数据库记录查询轻松解决
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- mysql查询后10条数据类型_30多条mysql数据库优化方法,千万级数据库记录查询轻松解决...
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- mysql每次查询1000条数据库_30多条mysql数据库优化方法,千万级数据库记录查询轻松解决...
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
最新文章
- jquery如何对多个对象绑定同一事件
- maven+SSM框架工程搭建
- 学计算机土味情话,计算机土味情话
- 瑞信中国前CEO唐臻怡加盟商汤科技出任副总裁
- 朱海舟宣布新一批应用已经适配锤子TNT 网友:救救海舟
- linux的文件权限前面的东西,linux 文件权限解析
- nested exception is java.lang.NoClassDefFoundError: org/codehaus/jettison/json/JSONObject异常的解决办法
- jni回调android子线程,如何在android的jni线程中实现回调
- 通信算法工程师调研整理
- html表格中文字换行设置
- 期望和方差的定义与性质
- 关于网页背景图怎样自动适应屏幕大小
- 计算机操作系统的加密与恢复,当在 Windows中设置 FIPS 兼容策略时,BitLocker 的恢复密码Windows...
- 面试须知的前端渲染和后端渲染
- 魅族 刷机android 6.0,乐视X800+安卓6.0.1 魅族Flyme6刷机包 最新6.7.12.29R版 紫火20180510更新...
- python statsmodels安装(亲测可用)
- MySQL趋势与前景技术分享
- 2021暑期学习第23天
- 纯净版安卓电子相册APP,安卓图片轮播
- Linux安装Oracle和postgrepSQL数据库
热门文章
- 【LTE】LTE轻松进阶学习笔记-扁平化的组网架构(3)
- BDBR和BD-PSNR说明
- 15拆分成3个不同的自然数_三年级常考的奥数题:整数拆分问题
- Centos 安装 OpenLDAP
- paper总结4——Latex排版伪代码一个大坑
- 网厨管理java_点菜网---Java开源生鲜电商平台-技术选型(源码可下载)
- 3D视觉应用案例:法兰件/引擎盖/控制臂上料,轮毂抓取上架
- initramfs unpacking failed: Decoding failed 无法安装ubuntu 联想台式机
- php 截取日期的年月,PHP截取日期
- 2021年4月股市行情预测