• 环境

    • 数据库: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栏关注我们,专注于程序员的技术公众号!」

千万级数据库使用索引查询速度更慢的疑惑-数据回表问题相关推荐

  1. python读取千万级数据库数据类型_解决python读取几千万行的大表内存问题

    Python导数据的时候,需要在一个大表上读取很大的结果集. 如果用传统的方法,Python的内存会爆掉,传统的读取方式默认在内存里缓存下所有行然后再处理,内存容易溢出 解决的方法: 1)使用SSCu ...

  2. 如何实现mysql千万级数据库插入速度和读取速度

    mysql千万级数据库插入速度和读取速度的调整记录 2018.11.1 Mysql version 5.7.23 一般情况下mysql上百万数据读取和插入更新是没什么问题了,但到了上千万级就会出现很慢 ...

  3. mysql数据库加载太慢_mysql千万级数据库插入速度和读取速度的调整记录

    一般情况下mysql上百万数据读取和插入更新是没什么问题了,但到了上千万级就会出现很慢,下面我们来看mysql千万级数据库插入速度和读取速度的调整记录吧. (1)提高数据库插入性能中心思想:尽量将数据 ...

  4. mysql千万级数据库插入速度和读取速度的调整记录。

    (1)提高数据库插入性能中心思想:尽量将数据一次性写入到Data File和减少数据库的checkpoint 操作.这次修改了下面四个配置项:           1)将 innodb_flush_l ...

  5. 整理:mysql千万级数据库插入速度和读取速度的调整

    一 1:innodb_flush_log_at_trx_commit参数解释:1:log buffer将每秒一次地写入log file中,并且log file的flush(刷到磁盘)操作同时进行.该模 ...

  6. mysql 分表索引_mysql中,分表查询和索引查询哪个更快?

    谢谢邀请! 查询快慢主决的因素有很多,存储碎片.数据量大属于I/O类问题:表结构设计.查询语句属于技术是否熟练(经验)问题.对于你的分表快还是索引快的这个问题本身就是有问题的: 在建立数据表的时候,索 ...

  7. 30多条mysql数据库优化方法,千万级数据库记录查询轻松解决

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  8. mysql查询后10条数据类型_30多条mysql数据库优化方法,千万级数据库记录查询轻松解决...

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  9. mysql每次查询1000条数据库_30多条mysql数据库优化方法,千万级数据库记录查询轻松解决...

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

最新文章

  1. jquery如何对多个对象绑定同一事件
  2. maven+SSM框架工程搭建
  3. 学计算机土味情话,计算机土味情话
  4. 瑞信中国前CEO唐臻怡加盟商汤科技出任副总裁
  5. 朱海舟宣布新一批应用已经适配锤子TNT 网友:救救海舟
  6. linux的文件权限前面的东西,linux 文件权限解析
  7. nested exception is java.lang.NoClassDefFoundError: org/codehaus/jettison/json/JSONObject异常的解决办法
  8. jni回调android子线程,如何在android的jni线程中实现回调
  9. 通信算法工程师调研整理
  10. html表格中文字换行设置
  11. 期望和方差的定义与性质
  12. 关于网页背景图怎样自动适应屏幕大小
  13. 计算机操作系统的加密与恢复,当在 Windows中设置 FIPS 兼容策略时,BitLocker 的恢复密码Windows...
  14. 面试须知的前端渲染和后端渲染
  15. 魅族 刷机android 6.0,乐视X800+安卓6.0.1 魅族Flyme6刷机包 最新6.7.12.29R版 紫火20180510更新...
  16. python statsmodels安装(亲测可用)
  17. MySQL趋势与前景技术分享
  18. 2021暑期学习第23天
  19. 纯净版安卓电子相册APP,安卓图片轮播
  20. Linux安装Oracle和postgrepSQL数据库

热门文章

  1. 【LTE】LTE轻松进阶学习笔记-扁平化的组网架构(3)
  2. BDBR和BD-PSNR说明
  3. 15拆分成3个不同的自然数_三年级常考的奥数题:整数拆分问题
  4. Centos 安装 OpenLDAP
  5. paper总结4——Latex排版伪代码一个大坑
  6. 网厨管理java_点菜网---Java开源生鲜电商平台-技术选型(源码可下载)
  7. 3D视觉应用案例:法兰件/引擎盖/控制臂上料,轮毂抓取上架
  8. initramfs unpacking failed: Decoding failed 无法安装ubuntu 联想台式机
  9. php 截取日期的年月,PHP截取日期
  10. 2021年4月股市行情预测