执行计划缓存视图 GV$OB_PLAN_CACHE_PLAN_STAT 视图中的 STATEMENT 和 QUERY_SQL 字段值是一样的

【 使用环境 】生产环境 or 测试环境
【 OB or 其他组件 】社区版OceanBase4.2.1.8
【 使用版本 】4.2.1.8
【问题描述】根据慢SQL的sql_id 值 通过 计划缓存视图查看 SQL语句 进行调优,发现QUERY_SQL字段中的SQL语句已经参数化,与statement字段值的SQL语句一样,这是什么情况?
【复现路径】问题出现前后相关操作
【附件及日志】推荐使用OceanBase敏捷诊断工具obdiag收集诊断信息,详情参见链接(右键跳转查看):

【SOP系列 22 】——故障诊断第一步(自助诊断和诊断信息收集)

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

在 OceanBase 4.2.1.8 社区版中,GV$OB_PLAN_CACHE_PLAN_STAT 视图的 STATEMENTQUERY_SQL 字段值相同,并且 QUERY_SQL 字段中的 SQL 语句已经参数化,这种情况通常是正常的。这两个字段都表示存储在计划缓存中的 SQL 语句,但它们可能在某些情况下有所不同:

  • STATEMENT 字段通常包含原始的 SQL 语句。
  • QUERY_SQL 字段则可能包含参数化后的 SQL 语句,用于提高执行效率和减少计划缓存的占用。

为了进一步确认这个问题,您可以使用 obdiag 工具进行日志采集,以便我们能够更详细地分析您的系统状态。

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

请您提供以下信息以便我们更好地帮助您:

  1. 您的 OceanBase 集群的具体配置信息,包括硬件配置和软件版本。
  2. 您遇到这个问题的具体场景,例如是在执行某个特定的 SQL 语句时出现的。
  3. 您是否有其他相关的日志或错误信息。
  4. 您是否尝试过其他方法来解决这个问题,如果有,请描述一下。
  5. 您是否可以提供一个具体的 SQL 语句示例,以便我们复现问题。

检索到的文档如下:

  1. 计划缓存相关视图
  2. 启用和关闭并行查询

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

1 个赞

把查询的信息 发一下 具体看看

query_sql字段值不应该是实际执行的SQL语句吗?

为参数化后的sql。

根据文档库中的信息,GV$OB_PLAN_CACHE_PLAN_STAT 视图中的 QUERY_SQL 字段确实通常包含参数化后的 SQL 语句,而不是实际执行的 SQL 语句。这种设计是为了提高执行效率和减少计划缓存的占用。

解释

  1. 参数化 SQL 语句

    • QUERY_SQL 字段中的 SQL 语句通常已经被参数化,这意味着其中的变量已经被占位符(如 ?%s)替换。这样做可以使得相同的 SQL 语句在不同的参数下重用同一个执行计划,从而提高性能。
  2. 原始 SQL 语句

    • STATEMENT 字段通常包含原始的 SQL 语句,即用户实际提交的 SQL 语句。这可以帮助您了解 SQL 语句的原始形态。

为什么 QUERY_SQLSTATEMENT 字段值相同

在某些情况下,QUERY_SQLSTATEMENT 字段的值可能会相同,这通常发生在以下几种情况:

  • 简单的 SQL 语句:如果 SQL 语句非常简单,没有参数化的需求,那么 QUERY_SQLSTATEMENT 字段的值可能会相同。
  • 未参数化:在某些情况下,OceanBase 可能没有对 SQL 语句进行参数化处理,导致 QUERY_SQLSTATEMENT 字段的值相同。

如何验证

如果您怀疑 QUERY_SQL 字段的值不正确,可以采取以下步骤进行验证:

  1. 检查 SQL 语句:确保您提交的 SQL 语句确实包含参数。
  2. 查看执行计划:使用 EXPLAIN 语句查看 SQL 语句的执行计划,确认是否进行了参数化。
  3. 日志分析:使用 obdiag 工具收集诊断信息,分析日志文件,查看 SQL 语句的执行过程。

示例

假设您有一个 SQL 语句:

SELECT * FROM test_pymysql WHERE id = 1;

GV$OB_PLAN_CACHE_PLAN_STAT 视图中,STATEMENTQUERY_SQL 字段的值可能如下:

  • STATEMENT: SELECT * FROM test_pymysql WHERE id = 1;
  • QUERY_SQL: SELECT * FROM test_pymysql WHERE id = ?;

如果 QUERY_SQL 字段的值与 STATEMENT 字段的值相同,那么可能是由于 SQL 语句没有被参数化。

总结

QUERY_SQL 字段通常包含参数化后的 SQL 语句,而 STATEMENT 字段包含原始的 SQL 语句。在某些情况下,这两个字段的值可能会相同,这并不一定是异常情况。如果您仍然怀疑有问题,建议使用 obdiag 工具进行进一步的日志分析。

希望这些信息对您有所帮助。如果还有其他问题,请随时联系 OceanBase 的人工答疑以获取更多帮助。 [1], [2]

检索到的文档如下:

  1. PyMySQL 连接 OceanBase 数据库示例程序
  2. 注释
  3. V$SQL_WORKAREA_ACTIVE
  4. GV$SQL_WORKAREA_ACTIVE

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

奇怪,之前查 GV$OB_PLAN_CACHE_PLAN_STAT 视图中的 QUERY_SQL 字段值都是实际执行的SQL啊

有记录么可以提供一下,或者你现在查一下该字段看看


这些? 都是参数化了的

是啊,很奇怪,昨晚刚从MySQL迁移过来

ob侧确实是参数化的展示

我觉得关于query_sql什么时候是参数化应该说明下,之前查都是标准的SQL语句,这次查是参数化形式,肯定是有原因的,要么就是BUG

这边查看官方文档中的说明 社区版最早3.1版本的gv$plan_cache_plan_stat
也是说明了是参数化的sql,你之前查询的原sql有例子保存么
https://www.oceanbase.com/docs/community-observer-cn-10000000000016896

1 个赞

所有执行的SQL语句都被参数化了

当 jdbc 驱动开启 服务端的 PreparedStatment 后就会这样, jdbc 参数:useServerPrepStmts

conn=jdbc:oceanbase://10.0.0.65:2883/tpcc?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&rewriteBatchedStatements=true&useLocalSessionState=false&useServerPrepStmts=true

压测 bmsql tpcc,观察 sql 审计视图

SELECT usec_to_time(request_time) req_time, tenant_name, DB_NAME,svr_ip,  client_ip,sid, plan_id, is_hit_plan, plan_type,  sql_id, query_sql, ret_code,elapsed_time, user_client_ip ,PS_CLIENT_STMT_ID,PS_INNER_STMT_ID, PARAMS_VALUE
FROM oceanbase.gv$ob_sql_audit
WHERE tenant_id = 1002  and plan_type in (1,2,3) and db_name in ('tpcc')  
ORDER BY request_time DESC LIMIT 100;

select tenant_id,svr_ip,plan_id,sql_id,statement,query_sql,ps_stmt_id,param_infos
from oceanbase.gv$ob_plan_cache_plan_stat where tenant_id=1002 and plan_id in (603)
;

JDBC 最佳实践: Java 应用与 OceanBase 数据库连接配置最佳实践-OceanBase 最佳实践文档-分布式数据库使用文档