TiDB算子简介
算子是为返回查询结果而执行的特定步骤。真正执行扫表(读盘或者读 TiKV Block Cache)操作的算子有如下几类:
- TableFullScan:全表扫描。
- TableRangeScan:带有范围的表数据扫描。
- TableRowIDScan:根据上层传递下来的 RowID 扫描表数据。时常在索引读操作后检索符合条件的行。
- IndexFullScan:另一种“全表扫描”,扫的是索引数据,不是表数据。
- IndexRangeScan:带有范围的索引数据扫描操作。
TiDB 会汇聚 TiKV/TiFlash 上扫描的数据或者计算结果,这种“数据汇聚”算子目前有如下几类:
- TableReader:将 TiKV 上底层扫表算子 TableFullScan 或 TableRangeScan 得到的数据进行汇总。
- IndexReader:将 TiKV 上底层扫表算子 IndexFullScan 或 IndexRangeScan 得到的数据进行汇总。
- IndexLookUp:先汇总 Build 端 TiKV 扫描上来的 RowID,再去 Probe 端上根据这些
RowID精确地读取 TiKV 上的数据。Build 端是IndexFullScan或IndexRangeScan类型的算子,Probe 端是TableRowIDScan类型的算子。 - IndexMerge:和
IndexLookupReader类似,可以看做是它的扩展,可以同时读取多个索引的数据,有多个 Build 端,一个 Probe 端。执行过程也很类似,先汇总所有 Build 端 TiKV 扫描上来的 RowID,再去 Probe 端上根据这些 RowID 精确地读取 TiKV 上的数据。Build 端是IndexFullScan或IndexRangeScan类型的算子,Probe 端是TableRowIDScan类型的算子。
算子的执行顺序
算子的结构是树状的,但在查询执行过程中,并不严格要求子节点任务在父节点之前完成。TiDB 支持同一查询内的并行处理,即子节点“流入”父节点。父节点、子节点和同级节点可能并行执行查询的一部分。
在以上示例中,├─IndexRangeScan_8(Build) 算子为 a(a) 索引所匹配的行查找内部 RowID。└─TableRowIDScan_9(Probe) 算子随后从表中检索这些行。
Build 总是先于 Probe 执行,并且 Build 总是出现在 Probe 前面。即如果一个算子有多个子节点,子节点 ID 后面有 Build 关键字的算子总是先于有 Probe 关键字的算子执行。TiDB 在展现执行计划的时候,Build 端总是第一个出现,接着才是 Probe 端。
范围查询
在 WHERE/HAVING/ON 条件中,TiDB 优化器会分析主键或索引键的查询返回。如数字、日期类型的比较符,如大于、小于、等于以及大于等于、小于等于,字符类型的 LIKE 符号等。
若要使用索引,条件必须是 "Sargable" (Search ARGument ABLE) 的。例如条件 YEAR(date_column) < 1992 不能使用索引,但 date_column < '1992-01-01 就可以使用索引。
推荐使用同一类型的数据以及同一类型的字符串和排序规则进行比较,以避免引入额外的 cast 操作而导致不能利用索引。
可以在范围查询条件中使用 AND(求交集)和 OR(求并集)进行组合。对于多维组合索引,可以对多个列使用条件。例如对组合索引 (a, b, c):
- 当
a为等值查询时,可以继续求b的查询范围。 - 当
b也为等值查询时,可以继续求c的查询范围。 - 反之,如果
a为非等值查询,则只能求a的范围。




