基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
TABLE SCAN
更新时间:2026-06-06 10:42:55
TABLE SCAN 算子是存储层和 SQL 层的接口,用于展示优化器选择哪个索引来访问数据。
在 OceanBase 数据库中,对于普通索引,索引的回表逻辑是封装在 TABLE SCAN 算子中的;而对于全局索引,索引的回表逻辑由 TABLE LOOKUP 算子完成。
示例:含 TABLE SCAN 算子的执行计划
obclient> CREATE TABLE t1(c1 INT PRIMARY KEY, c2 INT, c3 INT, c4 INT,
INDEX k1(c2,c3));
Query OK, 0 rows affected
Q1:
obclient> EXPLAIN EXTENDED SELECT * FROM t1 WHERE c1 = 1\G
*************************** 1. row ***************************
Query Plan: Plan signature: 12843576483891728377
==================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
----------------------------------
|0 |TABLE GET|t1 |1 |46 |
==================================
Outputs & filters:
-------------------------------------
0 - output([t1.c1(0x7f17bbe3a640)], [t1.c2(0x7f17bbe3aba0)], [t1.c3(0x7f17bbe3ae80)], [t1.c4(0x7f17bbe3b160)]), filter(nil), rowset=256,
access([t1.c1(0x7f17bbe3a640)], [t1.c2(0x7f17bbe3aba0)], [t1.c3(0x7f17bbe3ae80)], [t1.c4(0x7f17bbe3b160)]), partitions(p0),
is_index_back=false,
range_key([t1.c1(0x7f17bbe3a640)]), range[1 ; 1],
range_cond([t1.c1(0x7f17bbe3a640) = 1(0x7f17bbe39f60)])
Used Hint:
-------------------------------------
/*+
*/
Qb name trace:
-------------------------------------
stmt_id:0, stmt_type:T_EXPLAIN
stmt_id:1, SEL$1
Outline Data:
-------------------------------------
/*+
BEGIN_OUTLINE_DATA
FULL(@"SEL$1" "test_aaa"."t1"@"SEL$1")
OPTIMIZER_FEATURES_ENABLE('4.0.0.0')
END_OUTLINE_DATA
*/
Plan Type:
-------------------------------------
LOCAL
Optimization Info:
-------------------------------------
t1:table_rows:1, physical_range_rows:1, logical_range_rows:1, index_back_rows:0, output_rows:1, est_method:default_stat, optimization_method=rule_based, heuristic_rule=unique_index_without_indexback
Parameters:
-------------------------------------
1 row in set (0.00 sec)
Q2:
obclient> EXPLAIN EXTENDED SELECT * FROM t1 WHERE c2 < 1 AND c3 < 1 AND c4 < 1\G
*************************** 1. row ***************************
Query Plan: Plan signature: 12843576483891728377
===================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
-----------------------------------
|0 |TABLE SCAN|t1 |1 |46 |
===================================
Outputs & filters:
-------------------------------------
0 - output([t1.c1(0x7f174723d740)], [t1.c2(0x7f174723ae00)], [t1.c3(0x7f174723bff0)], [t1.c4(0x7f174723d1e0)]), filter([t1.c2(0x7f174723ae00) < 1(0x7f174723a720)], [t1.c3(0x7f174723bff0) < 1(0x7f174723b910)], [t1.c4(0x7f174723d1e0) < 1(0x7f174723cb00)]), rowset=256,
access([t1.c1(0x7f174723d740)], [t1.c2(0x7f174723ae00)], [t1.c3(0x7f174723bff0)], [t1.c4(0x7f174723d1e0)]), partitions(p0),
is_index_back=false, filter_before_indexback[false,false,false],
range_key([t1.c1(0x7f174723d740)]), range(MIN ; MAX)always true
Used Hint:
-------------------------------------
/*+
*/
Qb name trace:
-------------------------------------
stmt_id:0, stmt_type:T_EXPLAIN
stmt_id:1, SEL$1
Outline Data:
-------------------------------------
/*+
BEGIN_OUTLINE_DATA
FULL(@"SEL$1" "test_aaa"."t1"@"SEL$1")
OPTIMIZER_FEATURES_ENABLE('4.0.0.0')
END_OUTLINE_DATA
*/
Plan Type:
-------------------------------------
LOCAL
Optimization Info:
-------------------------------------
t1:table_rows:1, physical_range_rows:1, logical_range_rows:1, index_back_rows:0, output_rows:0, est_method:default_stat, optimization_method=cost_based, avaiable_index_name[k1,t1]
Parameters:
-------------------------------------
1 row in set (0.00 sec)
上述示例中,执行计划展示中的 outputs & filters 详细展示了 TABLE SCAN 算子的输出信息如下:
| 信息名称 | 含义 |
|---|---|
| operator | TABLE SCAN 算子的 operator 有两种形式:TABLE SCAN 和 TABLE GET。
|
| name | 选择用哪个索引来访问数据。选择的索引的名字会跟在表名后面,如果没有索引的名字,则说明执行的是主表扫描。 这里需要注意,在 OceanBase 数据库中,主表和索引的组织结构是一样的,主表本身也是一个索引。 |
| output | 该算子的输出列。 |
| filter | 该算子的过滤谓词。 由于示例中 Q1 查询的 TABLE GET 算子没有设置 filter,所以为 nil。 |
| partitions | 查询需要扫描的分区。 |
| is_index_back | 该算子是否需要回表。 例如,在 Q1 查询中,因为选择了主表,所以不需要回表。在 Q2 查询中,索引列是 (c2,c3,c1), 由于查询需要返回 c4 列,所以需要回表。 |
| filter_before_indexback | 与每个 filter 对应,表明该 filter 是可以直接在索引上进行计算,还是需要索引回表之后才能计算。 例如,在 Q2 查询中,当 filter 为 c3 < 1 时, 可以直接在索引上计算,能减少回表数量;当 filter 为 c4 < 1 时,需要回表取出 c4 列之后才能计算。 |
| range_key/range/range_cond |
|