TiDB与MySQL的SQL差异及执行计划简析
作者:京东零售 肖勇
一、 前言导读
TiDB作为NewSQL,其在对MySQL(SQL92协议)的兼容上做了很多,MySQL作为当下使用较广的事务型数据库,在IT界尤其是互联网间使用广泛,那么对于开发人员来说,1)两个数据库产品在SQL开发及调优的过程中,都有哪些差异?在系统迁移前需要提前做哪些准备? 2)TiDB的执行计划如何查看,如何SQL调优? 本文做了一个简要归纳,欢迎查阅交流。
二、 建表SQL语法差异&优化建议
三、 查询SQL语法差异&优化建议
四、 SQL执行计划差异&优化建议
五、 TiDB执行计划分析简介
1. 在开始实际案例分析前,我们先看下执行计划中每列的含义:
2. 执行计划优化的几个关键点:
1) 重点观察算子类型,尽量控制优化器选择性能较优的算子,读取磁盘记录的几个算子性能:TableFullScan>TableRangeScan>TableRowIDScan,IndexFullScan>IndexRangeScan
2) 尽量减小root层执行动作,下放至tikv或tiflash执行,执行计划中task属性包括root task和cop task,其中root标识动作由tidb聚合层执行(此操作除了需要等待各分片结果外,一般部署结构中tidb资源也较tikv或tiflash少),cop标识动作下放至tikv或tiflash各分片单独执行
3) 保证表分析数据完整性,避免大批量数据短时间内新增/删除,estRows为执行引擎根据情况返回的预估记录条数,特别注意:若operator info出现stats:pseudo,则标识表基本信息不完善(无法提供准确执行计划评估),后续可通过analyze表重新收集分析数据,或显示use index对sql显示优化
4) 根据实际业务(如:列模式数据统计),增加tiflash模块,通过空间换时间,提升结构化查询和实时分析能力
3. 实际场景分析
下面我们通过2个实际SQL说说TiDB的执行计划:
l SQL1
1:IndexLookUp算子:根据索引获取结果记录
2 & 3:Build算子总是优先于Probe算子执行,*2 算子根据条件从索引中获取数据,*3算子在结果中匹配结果
4:TableRowIdScan:通过 *3 算子结果中的表主键id从TiKV获取行记录
5:cop【tikv】标识将计算逻辑从tidb下放到tikv执行,同理还会有cop【tiflash】
6:tikv通过范围索引扫描出对应记录
7:根据id获取行记录后直接返回上层,无需排序
------------------------------------------------------------------------------------------------------------------------------
l SQL2
优化前,两表直接join:
explain analyze SELECT m.id AS id, m.order_id AS orderId, s.status AS status,m.sendpay_map as sendPayMap FROM tableA m LEFT JOIN tableB s on m.order_id = s.order_id WHERE m.id >= 100 AND m.id <= 100000000 and m.warehouse_id in (111,222) and s.status in (100, 200, 300, 400) and m.is_valid = 1 order by m.id desc limit 20,20;
1:IndexJoin算子:根据表s索引,与表m关联起来
2 & 3:Build算子总是优先于Probe算子执行,*2 算子从表m匹配相关记录,*3算子通过表s索引获取join管理数据
4 & 5:基于*3算子join后的结果,筛选匹配s表条件的记录
6 & 7:可以看到此处表记录查询使用了TableReader,耗时6.41s(其中cop_task共424个,且使用了大量索引proc_keys),Selection_98根据索引回表查询更是读取了3.03GB记录
总结:整体sql因为是先join在limit,tidb无法将limit操作下推,导致主表大量回表查询,影响性能
优化后,先子查询再join:
explain analyze select * from (SELECT m.id AS id, m.order_id AS orderId,m.sendpay_map as sendPayMap FROM tableA m WHERE m.id >= 100 AND m.id <= 100000000 and m.warehouse_id in (111 ,222) and m.is_valid = 1 order by m.id desc limit 20,20) t LEFT JOIN tableB s on t.orderId = s.order_id WHERE s.status in (100 ,200, 300, 400)
1:IndexJoin算子:根据表s索引,与表m关联起来
2:从m表结果中获取前20条记录
3:通过表s索引获取join管理数据
4:根据条件,从表m的索引中获取记录
5:从*4算子结果中获取40条记录(tikv3副本,从2个分片各获取20条,共40条)
6 & 7:基于*3算子join后的结果,筛选匹配s表条件的记录
9:可以看到,此处是直接从IndexLookUp_57索引中查询数据,cop_task=1,且rocksdb中命中了缓存cache_hit_count=11
总结:整体sql因为是先limit再join,tidb将limit下推至tikv,大大较少了主表的回表查询数据量,提升性能
六、 小结
本文旨在通过TiDB和MySQl在SQL层面的差异性讲解,帮助读者在DB迁移和评估前,清楚了解双方的差异,避免遗漏。同时,针对TiDB的执行计划,通过简介和2个案例,帮助大家快速分析SQL执行情况,以便针对性优化。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
缓存空间优化实践
作者:京东科技 董健 导读 缓存Redis,是我们最常用的服务,其适用场景广泛,被大量应用到各业务场景中。也正因如此,缓存成为了重要的硬件成本来源,我们有必要从空间上做一些优化,降低成本的同时也会提高性能。 下面以我们的案例说明,将缓存空间减少70%的做法。 场景设定 1、我们需要将POJO存储到缓存中,该类定义如下 public class TestPOJO implements Serializable { private String testStatus; private String userPin; private String investor; private Date testQueryTime; private Date createTime; private String bizInfo; private Date otherTime; private BigDecimal userAmount; private BigDecimal userRate; private BigDecimal applyAmount; private Stri...
- 下一篇
一款能“干掉” ChatGPT 的应用「GitHub 热点速览」
据说有了它,ChatGPT 就可以靠边站了。因为 Auto-GPT 能更加主动地完成你给他的指定任务,不用做更多的人为干涉,它的推理能力比 ChatGPT 更强,有人用它解放双手做了个 React 网站。当然除了升级的 Auto-GPT 之外,还有 DeepSpeed,它能极大地降低训练成本。这两个项目可是本周的明星项目,一个获得 50k+ star ,一个是 10k+。 当然还有非常有意思的,让你的 2D 卡通人物动起来的 AnimatedDrawings,沙雕又可爱。既然是动画,就不能不提下腾讯的动效渲染库 libpag,以及知名老牌 macOS 资源监控项目 stats。 以下内容摘录自微博@HelloGitHub 的 GitHub Trending 及 Hacker News 热帖(简称 HN 热帖),选项标准:新发布 | 实用 | 有趣,根据项目 release 时间分类,发布时间不超过 14 day 的项目会标注 New,无该标志则说明项目 release 超过半月。由于本文篇幅有限,还有部分项目未能在本文展示,望周知 🌝 本文目录 1. 本周特推 1.1 AI 专场 1...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- 2048小游戏-低调大师作品