关于tidb:TiDB与MySQL的SQL差异及执行计划简析

7次阅读

共计 2562 个字符,预计需要花费 7 分钟才能阅读完成。

作者:京东批发 肖勇

一、前言导读

TiDB 作为 NewSQL,其在对 MySQL(SQL92 协定)的兼容上做了很多,MySQL 作为当下应用较广的事务型数据库,在 IT 界尤其是互联网间应用宽泛,那么对于开发人员来说,1)两个数据库产品在 SQL 开发及调优的过程中,都有哪些差别?在零碎迁徙前须要提前做哪些筹备?2)TiDB 的执行打算如何查看,如何 SQL 调优?本文做了一个简要演绎,欢送查阅交换。

二、建表 SQL 语法差别 & 优化倡议

三、查问 SQL 语法差别 & 优化倡议

四、SQL 执行打算差别 & 优化倡议

五、TiDB 执行打算剖析简介

1. 在开始理论案例剖析前,咱们先看下执行打算中每列的含意:

引自:https://docs.pingcap.com/zh/tidb/stable/sql-statement-explain 和 https://docs.pingcap.com/zh/tidb/stable/sql-statement-explain-analyze

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 执行状况,以便针对性优化。

正文完
 0