DISTRIBUTED TABLE RANGE SCAN

图片

案例一 和 案例二 , 并没有不同。

案例二的表仅仅只是多col3列。

那,为什么同样的查询语句,执行计划会不同呢 ?

8 个赞

支持支持

1 个赞

2个查询的OPERATEOR不同。

4 个赞

加油

1 个赞
特性 TABLE RANGE SCAN DISTRIBUTED TABLE RANGE SCAN
执行位置 单个 OBServer 节点 多个 OBServer 节点(分布式)
是否涉及 RPC 否(本地执行) 是(需远程调用)
适用场景 数据局部性好、可下推 跨分区/跨节点查询
3 个赞

@论坛小助手

您的问题关于为什么在添加了一个额外的列(col3)之后,同样的查询语句会产生不同的执行计划。这主要涉及到 OceanBase 数据库如何优化查询以及索引的使用策略。

解释案例一与案例二的不同

  • 案例一:只有两列 (col1, col2) 的情况下,使用了 TABLE RANGE SCAN 操作符。
  • 案例二:添加了第三列 (col3) 后,使用了 DISTRIBUTED TABLE RANGE SCAN 操作符。

原因分析

1. 索引覆盖性

  • 在第一个案例中,idx2 索引仅包含 col2 列,而查询需要返回所有列(*)。因此,即使 col2 的值小于2,也需要通过主键查找其他列的值(col1),这导致了 TABLE RANGE SCAN
  • 在第二个案例中,虽然 idx2 索引还是只包含 col2 列,但查询仍然需要返回所有列(包括新添加的 col3)。由于 col3 不在索引中,数据库可能选择了一种更复杂的分布式的范围扫描方式来获取数据,这就是 DISTRIBUTED TABLE RANGE SCAN

2. 分布式特性

  • DISTRIBUTED TABLE RANGE SCAN 是一种分布式操作,它可以在多个节点上并行执行范围扫描,从而提高查询性能。这种操作符在处理大量数据时更为有效。
  • 当表中增加了一个新的列,并且这个列不在索引中时,数据库为了确保能够高效地获取到所有需要的数据,可能会选择使用分布式的方式来执行查询。

结论

  • 索引覆盖性:在第一个案例中,索引可以覆盖查询所需的部分数据,而在第二个案例中,由于新增的列不在索引中,导致需要进行更多的数据访问。
  • 分布式特性:为了提高查询性能,特别是在处理大量数据时,OceanBase 可能会选择使用分布式的方式来进行范围扫描。

希望这些解释能帮助您理解为什么在添加了一个额外的列后,查询的执行计划会有所不同。如果还有其他问题,请随时提问!

详情请参考:

  1. 常见的 SQL 调优方式
  2. GENERATOR
  3. 基于规则的查询改写
2 个赞

分布式表,指的是表有多个分区,并且这多个分区分布在多个节点上的意思 ? @论坛小助手

1 个赞

您的理解是正确的。在OceanBase这样的分布式数据库中,"分布式表"确实指的是该表的数据被划分成多个分区,并且这些分区分布在集群中的多个节点上。这种设计的主要目的是为了实现数据的水平扩展以及提高系统的整体处理能力和容错性。

分布式表的特点

  1. 分区:通过定义不同的分区策略(如Hash分区、Range分区等),可以将一张表的数据分成多个部分存储。
  2. 多节点分布:每个分区可以存储在不同的物理节点上,这使得数据可以均匀地分布在多个机器上,从而实现负载均衡和高可用性。
  3. 水平扩展:随着数据量的增长,可以通过增加更多的节点来扩展系统容量,而不需要对单个节点进行垂直升级。
  4. 并行处理:由于数据分布在多个节点上,查询可以在多个节点上并行执行,从而加快了处理速度。
  5. 容错能力:即使某个节点出现故障,其它节点上的数据仍然可以继续提供服务,保证了系统的高可用性。

示例

以您提供的案例为例,表 t1 通过 partition by hash(col1) partitions 5 定义了5个分区,这些分区根据 col1 的值通过哈希函数计算后被分配到集群的不同节点上。这样做的好处包括但不限于:

  • 支持大规模数据集的存储与管理;
  • 提升查询性能,特别是对于涉及范围扫描或特定条件过滤的操作;
  • 实现故障隔离,当某一节点发生故障时不影响其他节点正常工作;

希望这能帮助您更好地理解分布式表的概念及其在OceanBase中的应用方式。如果还有进一步的问题,请随时提问!

检索到的文档如下:

  1. 表组
  2. 数据分布
  3. 租户内均衡
  4. 通用语法
  5. 分布式计划的生成
  6. 分区分裂概述
1 个赞

分布查询性能会差,尽量本地

1 个赞

支持

图片
如上图,执行的是唯一索引的等值查询,那么执行计划的算子为什么不是table get ,而是table range scan? @论坛小助手 请解答一下

根据您提供的信息和OCR提取的文本内容,您提到的是一个唯一索引的等值查询。在理想情况下,对于唯一索引的等值查询,OceanBase 通常会使用 TABLE GET 算子来直接获取单行数据。然而,在您的例子中,执行计划显示使用了 TABLE RANGE SCAN 算子。这可能有几个原因:

可能的原因

  1. 统计信息不准确

    • 如果表的统计信息不准确或过时,优化器可能无法正确估计唯一索引的过滤性,从而选择 TABLE RANGE SCAN 而不是 TABLE GET
  2. 索引选择策略

    • 优化器可能会基于其他因素(如查询条件的复杂性、数据分布等)选择 TABLE RANGE SCAN 而不是 TABLE GET。虽然 TABLE GET 适用于唯一索引的等值查询,但优化器可能认为 TABLE RANGE SCAN 在某些情况下更优。
  3. 配置或版本差异

    • 不同的 OceanBase 版本或不同的配置参数可能会影响优化器的选择。例如,某些配置可能影响优化器对索引的选择。
  4. 全局索引的影响

    • 您创建的索引是全局索引(GLOBAL),这意味着索引的数据分布在多个节点上。在这种情况下,优化器可能选择 TABLE RANGE SCAN 来更好地处理分布式环境中的数据访问。

具体分析

  • 唯一索引的等值查询:对于唯一索引的等值查询,通常 TABLE GET 是最优选择,因为它可以直接定位到唯一的行。
  • 执行计划:在您的例子中,TABLE RANGE SCAN 的使用可能是因为优化器认为在这种情况下 TABLE RANGE SCAN 更适合。具体来说,TABLE RANGE SCAN 仍然可以有效地找到唯一的一行数据,尤其是在全局索引的情况下。

解决方法

  1. 更新统计信息

    • 尝试更新表的统计信息,确保优化器能够获得最新的数据分布情况。
    ANALYZE TABLE t1;
    
  2. 强制使用 TABLE GET

    • 如果您确定 TABLE GET 是最优选择,可以尝试使用 Hint 来强制优化器使用 TABLE GET
    EXPLAIN SELECT /*+ USE_INDEX(t1 idx1) */ c1 FROM t1 WHERE c1 = 1;
    
  3. 检查配置

    • 检查 OceanBase 的配置参数,确保没有影响优化器选择的特定设置。

结论

在您的案例中,优化器选择了 TABLE RANGE SCAN 而不是 TABLE GET,这可能是由于统计信息不准确、优化器的索引选择策略或其他配置因素。建议您更新统计信息并尝试使用 Hint 来强制优化器使用 TABLE GET。如果问题仍然存在,可能需要进一步检查具体的配置和环境。

希望这些解释能帮助您理解为什么会出现这种情况。如果还有其他问题,请随时提问!

具体信息可参考以下文档:

  1. 阅读和管理 OceanBase 数据库 SQL 执行计划
  2. 诊断实践:使用 SQL_PLAN_MONITOR 分析性能问题
  3. 分布式计划的生成
  4. 基于规则的路径选择
  5. Optimizer Hint
  6. 存储层估行


如上图,同样的查询语句,为什么执行计划不同?
@论坛小助手 请解答一下

根据您提供的信息和OCR提取的文本内容,您展示了两个不同的执行计划,尽管查询语句是相同的。让我们详细分析一下这两个执行计划的不同之处以及可能的原因。

执行计划对比

案例一:使用全局索引

create table t1(col1 int primary key, col2 int, col3 int) partition by hash(col1) partitions 5;
create index idx2 on t1(col2) GLOBAL;

explain select * from t1 where col2 < 2;

执行计划:

| ID | OPERATOR INAME                   | EST. ROWS | EST. TIME(us) |
|----|----------------------------------|-----------|---------------|
| 0  | DISTRIBUTED TABLE RANGE SCAN      | t1(idx2)  | 1             |

outputs & filters:
0 - output([t1.col1], [t1.col2], [t1.col3]), filter(nil), rowset=16
access([t1.col1], [t1.col2], [t1.col3]), partitions(p0)
is_index_back=true, is_global_index=true, keep_ordering=true,
range_key([t1.col2], [t1.col1]), range(NULL,MAX ; 2,MIN),
range_cond([t1.col2] < 2)

案例二:使用本地索引

create table t1(col1 int primary key, col2 int, col3 int) partition by hash(col1) partitions 5;
create index idx1 on t1(col2);

explain select * from t1 where col2 < 2;

执行计划:

| ID | OPERATOR INAME                   | EST. ROWS | EST. TIME(us) |
|----|----------------------------------|-----------|---------------|
| 0  | PX COORDINATOR                   | 1         | 25            |
| 1  | └─EXCHANGE OUT DISTR              | :EX10000  | 1             |
| 2  |   └─PX PARTITION ITERATOR        |           | 1             |
| 3  |     └─TABLE RANGE SCAN            | t1(idx1)  | 1             |

outputs & filters:
0 - output([INTERNAL_FUNCTION(t1.col1, t1.col2, t1.col3)]), filter(nil), rowset=16
1 - output([INTERNAL_FUNCTION(t1.col1, t1.col2, t1.col3)]), filter(nil), rowset=16, dop=1
2 - output([t1.col1], [t1.col2], [t1.col3]), filter(nil), rowset=16
force partition granule
3 - output([t1.col1], [t1.col2], [t1.col3]), filter(nil), rowset=16
access([t1.col1], [t1.col2], [t1.col3]), partitions(p0-4)
is_index_back=true, is_global_index=false,
range_key([t1.col2], [t1.col1]), range(NULL,MAX ; 2,MIN),
range_cond([t1.col2] < 2)

分析

  1. 索引类型不同

    • 案例一:使用的是全局索引 idx2。全局索引的数据分布在多个节点上。
    • 案例二:使用的是本地索引 idx1。本地索引的数据与表数据一起存储在同一个分区中。
  2. 执行计划差异

    • 案例一:使用了 DISTRIBUTED TABLE RANGE SCAN 算子。这表明优化器认为通过全局索引进行分布式范围扫描是最优的选择。
    • 案例二:使用了 PX COORDINATOREXCHANGE OUT DISTRPX PARTITION ITERATOR 算子,最终使用 TABLE RANGE SCAN 算子。这表明优化器选择了并行处理的方式来执行查询,并且使用本地索引来访问数据。

可能的原因

  1. 全局索引 vs 本地索引

    • 全局索引的数据分布在多个节点上,因此适合使用分布式范围扫描来快速定位数据。
    • 本地索引的数据与表数据一起存储在同一个分区中,因此更适合使用并行处理的方式来提高查询性能。
  2. 优化器的选择

    • 优化器会根据索引类型、数据分布、查询条件等因素来选择最优的执行计划。在案例一中,优化器认为分布式范围扫描更优;而在案例二中,优化器认为并行处理更优。

结论

  • 案例一:使用全局索引 idx2,执行计划选择了 DISTRIBUTED TABLE RANGE SCAN,因为全局索引的数据分布在多个节点上,适合分布式范围扫描。
  • 案例二:使用本地索引 idx1,执行计划选择了并行处理的方式,使用 PX COORDINATOREXCHANGE OUT DISTRPX PARTITION ITERATOR 算子,最终使用 TABLE RANGE SCAN 算子,因为本地索引的数据与表数据一起存储在同一个分区中,适合并行处理。

希望这些解释能帮助您理解为什么同样的查询语句会有不同的执行计划。如果还有其他问题,请随时提问!

详情请参考:

  1. Optimizer Hint
  2. 设置并行执行并行度

学习一下

两个案例计划不同,主要看全局索引能不能覆盖 select 的列。案例一表里只有 col1、col2,全局索引 idx2(col2) 本身已包含主键 col1,能覆盖 select *,所以直接走索引不回表(is_index_back=false);案例二多了 col3,索引覆盖不到,select * 必须回表取数,代价变了,执行计划自然就不同了。

1 个赞

第二个用的是das获取数据方式,如果数据不在本节点,并且数据量比较少,那么通过存储层rpc方式将远程数据get过来。如果在本地就不用了。