sql 包含in解析时间过长

【 使用环境 】生产环境
【 OB or 其他组件 】ob
【 使用版本 】4.3.5.0
【问题描述】sql where 条件包含in值过长,导致解析时间过长
【复现路径】问题出现前后相关操作
【附件及日志】

【备注】基于 LLM 和开源文档 RAG 的论坛小助手已开放测试,在发帖时输入 [@论坛小助手] 即可召唤小助手,欢迎试用!

根因分析场景: SQL性能问题
根因分析命令: obdiag rca run --scene=sql_performance_issue
日志采集场景: SQL性能问题
日志采集命令: obdiag gather scene run --scene=observer.perf_sql --env “{db_connect=’-h127.0.0.1 -P2881 -utest@test -p****** -Dtest’, trace_id=‘Yxx’}”

为了更好地帮助您解决 SQL 性能问题,请您按照上述命令进行日志采集,并将生成的日志压缩包提供给我们。同时,为了更精准地定位问题,请您回答以下问题:

  1. 您的 OceanBase 数据库版本是多少?
  2. 当前 SQL 的 in 值列表中包含多少个值?是否可以提供一个具体的示例 SQL 语句(请脱敏敏感信息)?
  3. 是否可以通过 EXPLAIN 查看该 SQL 的执行计划?如果有,请一并提供。
  4. 您是否有尝试过将 in 值列表拆分为多个小批次执行?效果如何?
  5. 数据表的结构是否可以提供?特别是涉及 in 条件的字段是否有索引?
  6. 是否可以启用慢查询日志来捕获此类 SQL 的详细信息?如果可以,请提供相关的慢查询日志片段。

附上敏捷诊断工具 obdiag 使用帮助链接

根据您提供的信息和图片内容,SQL 的执行计划显示了性能瓶颈可能与 IN 条件中的值过多有关。以下是一些分析和建议:


问题分析

  1. SQL 执行计划

    • 从执行计划中可以看到,PHY_VEC_TABLE SCAN 是主要的执行步骤,且涉及大量数据扫描。
    • table_rowsphysical_range_rows 的值较大,表明查询需要扫描大量数据。
  2. CPU 消耗高

    • 图片中显示 CPU BYE 时间为 122308ms,说明 CPU 在处理该 SQL 时消耗了较多时间。
    • 这可能是由于 IN 条件中的值过多,导致解析和匹配过程复杂度增加。
  3. IN 条件的影响

    • IN 条件中的值列表过长时,数据库需要逐一匹配这些值,可能导致解析时间和执行时间显著增加。
    • 如果 IN 列表中的值没有索引支持,可能会导致全表扫描,进一步降低性能。

解决方案

1. 优化 IN 条件

  • 拆分 IN 值列表
    将长的 IN 条件拆分为多个小批次,分别执行查询。例如:

    -- 原始 SQL
    SELECT * FROM table_name WHERE column_name IN (value1, value2, ..., valueN);
    
    -- 拆分后
    SELECT * FROM table_name WHERE column_name IN (value1, value2, ..., valueM);
    UNION ALL
    SELECT * FROM table_name WHERE column_name IN (valueM+1, ..., valueN);
    

    这种方式可以减少单次查询的解析和执行时间。

  • 使用临时表替代 IN 条件
    IN 条件中的值存储到一个临时表中,并通过 JOIN 查询替代 IN 条件。例如:

    -- 创建临时表
    CREATE TEMPORARY TABLE temp_values (
        value_column VARCHAR(255)
    );
    
    -- 插入 IN 条件中的值
    INSERT INTO temp_values (value_column) VALUES ('value1'), ('value2'), ..., ('valueN');
    
    -- 使用 JOIN 替代 IN
    SELECT t.* 
    FROM table_name t
    JOIN temp_values v ON t.column_name = v.value_column;
    

2. 添加索引

  • 确保 IN 条件中涉及的字段有适当的索引。如果没有索引,数据库可能会进行全表扫描,导致性能下降。
  • 示例:
    CREATE INDEX idx_column_name ON table_name (column_name);
    

3. 调整 SQL 语句

  • 如果 IN 条件中的值可以通过子查询生成,可以尝试将 IN 替换为 EXISTSJOIN。例如:
    -- 原始 SQL
    SELECT * FROM table_name WHERE column_name IN (subquery);
    
    -- 替换为 EXISTS
    SELECT * FROM table_name t
    WHERE EXISTS (SELECT 1 FROM subquery_table s WHERE t.column_name = s.value_column);
    
    -- 或者替换为 JOIN
    SELECT DISTINCT t.*
    FROM table_name t
    JOIN subquery_table s ON t.column_name = s.value_column;
    

4. 启用并行查询

  • 如果数据量较大,可以启用并行查询以加速执行。例如:
    /*+ PARALLEL(table_name, 4) */
    SELECT * FROM table_name WHERE column_name IN (value1, value2, ..., valueN);
    

5. 检查统计信息

  • 确保表的统计信息是最新的,以便优化器能够生成更优的执行计划。例如:
    ANALYZE TABLE table_name COMPUTE STATISTICS;
    

总结

根据您的描述和提供的执行计划,SQL 性能问题的主要原因是 IN 条件中的值过多,导致解析和执行时间过长。建议您尝试以下方法优化:

  1. 拆分 IN 条件或使用临时表替代。
  2. 确保相关字段有索引支持。
  3. 调整 SQL 语句结构,例如使用 EXISTSJOIN
  4. 启用并行查询以加速执行。
  5. 更新表的统计信息以优化执行计划。

如果问题仍未解决,请提供以下信息以便进一步分析:

  • 具体的 SQL 语句(脱敏敏感信息)。
  • 表的结构定义(包括索引信息)。
  • EXPLAIN 输出的完整执行计划。

希望以上建议对您有所帮助!

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

  1. 过期数据删除
  2. oceanbase.DBA_SUBPART_HISTOGRAMS
  3. DISPLAY_SQL_PLAN_BASELINE
  4. oceanbase.DBA_PART_HISTOGRAMS
  5. V$ENCRYPTED_TABLESPACES

(小助手的答复已结束,如未能解决您的问题,请继续提问并等待其他同学的回复,谢谢!)

链接:https://foreignfile.catl.com/outpublish.html?code=Ab7208ec27c234c4698d7b4c8f654c6aa&lang=zh-cn#view
密码:63B83A11
文本信息如下

ob小助手讲的比较全面了

不错,学习了

语句为框架中的语句,无法修改.
表不是很大,分别为75w,和32w
image

1.SQL 详情收集
gv$ob_sql_audit 通过这个视图 查询一下sql执行的trace_id
obdiag gather plan_monitor --trace_id YB420BA2D99B-0005EBBFC45D5A00-0-0 --env"{db_connect=’-hxx -Pxx -uxx -pxx -Dxx’}"

收集以后 提供一下

稍等下,我收集下

链接:https://foreignfile.catl.com/outpublish.html?code=A8bb286d4cebf4fc0b3f6a0a74dc1d650&lang=zh-cn#view
密码:FC472490

可以直接把收集的信息 发到帖子上么?无法下载 打开以后 下载无响应

这个网址没法上传文件,之前 旭辉他们是可以的,把安全网关关了之后试试


那你发给旭辉吧 让他转给我一下

那个网盘连接旭辉可以直接打开的

ob是4350么?SHOW VARIABLES like ‘version_comment’;查一下