某业务从MySQL迁移到OceanBase后,发现一个简单的两表Join查询(左表1000行,右表1亿行)性能下降了1000倍。查看执行计划发现,优化器选择了Nested Loop Join ,并且右表被反复扫描了1000次,且每次扫描都涉及跨节点远程调用。这种“跨机 Rescan”现象是如何产生的?OceanBase 4.x 版本提供了什么内核级优化手段来解决这个问题?
可以把具体的语句发出来 使用obdiag收集一下
https://www.oceanbase.com/docs/common-obdiag-cn-1000000005357969
obdiag gather plan_monitor --trace_id YB420BA2D99B-0005EBBFC45D5A00-0-0
–env host=xx.xx.xx.xx --env port=2881 --env user=root@test --env password=*** --env database=test
您好!关于您提到的“跨机 Rescan”问题,确实是一个值得关注的性能问题。在 OceanBase 4.x 版本中,有一些内核级的优化手段可以帮助解决这类问题。以下是详细的解释:
跨机 Rescan 现象的产生
- 查询优化器选择:优化器选择了 Nested Loop Join 这种执行计划。
- 右表的反复扫描:左表每有一行数据,右表就需要被扫描一次,导致右表被反复扫描了1000次。
- 跨节点远程调用:由于数据分布在不同的节点上,每次扫描都会涉及跨节点的远程调用,增加了网络开销。
解决方案
-
调整优化器行为:
-
修改优化器参数:可以通过调整优化器参数来影响查询计划的选择。例如,可以尝试设置
optimizer_join_order参数来控制 join 的顺序。 -
使用 Hint:在 SQL 语句中使用 Hint 来强制指定优化器使用特定的执行计划。例如,可以使用
/*+ USE_HASH_JOIN */来强制使用 Hash Join。
-
修改优化器参数:可以通过调整优化器参数来影响查询计划的选择。例如,可以尝试设置
-
数据分布优化:
- 分区表:将大表进行分区,可以减少跨节点的数据传输。可以考虑使用范围分区、哈希分区等策略。
- 局部索引:在分区表上创建局部索引,可以进一步提高查询性能。
-
并行查询:
-
启用并行查询:OceanBase 支持并行查询,可以通过设置
parallel_query参数来启用并行查询,从而加速查询执行。
-
启用并行查询:OceanBase 支持并行查询,可以通过设置
-
SQL 调优:
- 重写 SQL:优化 SQL 语句本身,尽量减少不必要的 join 操作,或者优化 join 条件。
示例
假设您的 SQL 语句如下:
SELECT * FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id;
可以尝试以下优化:
-
使用 Hint 强制使用 Hash Join:
SELECT /*+ USE_HASH_JOIN(t1, t2) */ * FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id; -
分区表:
CREATE TABLE table2 ( id INT PRIMARY KEY, ... ) PARTITION BY HASH(id) PARTITIONS 16; -
启用并行查询:
SET parallel_query = 'ON'; SELECT * FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id;
收集诊断信息
如果上述方法仍然无法解决问题,建议使用 obdiag 工具收集诊断信息,以便进一步分析。具体步骤如下:
-
安装
obdiag工具:pip install obdiag -
收集诊断信息:
obdiag gather plan_monitor --trace_id <trace_id> --env host=<host> --env port=<port> --env user=<user> --env password=<password> --env database=<database>
希望这些方法能帮助您解决“跨机 Rescan”的问题。如果有更多问题或需要进一步的帮助,请随时联系 OceanBase 技术支持。
具体信息可参考以下文档:
多种应对思路:
- 调整 租户 primary_zone 为 单 zone
- 用表组