【 使用环境 】生产环境 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 的论坛小助手已开放测试,在发帖时输入 [@论坛小助手 ] 即可召唤小助手,欢迎试用!
论坛小助手
2024 年11 月 1 日 14:23
#3
在 OceanBase 4.2.1.8 社区版中,GV$OB_PLAN_CACHE_PLAN_STAT
视图的 STATEMENT
和 QUERY_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’}”
请您提供以下信息以便我们更好地帮助您:
您的 OceanBase 集群的具体配置信息,包括硬件配置和软件版本。
您遇到这个问题的具体场景,例如是在执行某个特定的 SQL 语句时出现的。
您是否有其他相关的日志或错误信息。
您是否尝试过其他方法来解决这个问题,如果有,请描述一下。
您是否可以提供一个具体的 SQL 语句示例,以便我们复现问题。
检索到的文档如下:
计划缓存相关视图
启用和关闭并行查询
附上敏捷诊断工具 obdiag 使用帮助链接
1 个赞
query_sql字段值不应该是实际执行的SQL语句吗?
论坛小助手
2024 年11 月 1 日 14:43
#7
根据文档库中的信息,GV$OB_PLAN_CACHE_PLAN_STAT
视图中的 QUERY_SQL
字段确实通常包含参数化后的 SQL 语句,而不是实际执行的 SQL 语句。这种设计是为了提高执行效率和减少计划缓存的占用。
解释
参数化 SQL 语句 :
QUERY_SQL
字段中的 SQL 语句通常已经被参数化,这意味着其中的变量已经被占位符(如 ?
或 %s
)替换。这样做可以使得相同的 SQL 语句在不同的参数下重用同一个执行计划,从而提高性能。
原始 SQL 语句 :
STATEMENT
字段通常包含原始的 SQL 语句,即用户实际提交的 SQL 语句。这可以帮助您了解 SQL 语句的原始形态。
为什么 QUERY_SQL
和 STATEMENT
字段值相同
在某些情况下,QUERY_SQL
和 STATEMENT
字段的值可能会相同,这通常发生在以下几种情况:
简单的 SQL 语句 :如果 SQL 语句非常简单,没有参数化的需求,那么 QUERY_SQL
和 STATEMENT
字段的值可能会相同。
未参数化 :在某些情况下,OceanBase 可能没有对 SQL 语句进行参数化处理,导致 QUERY_SQL
和 STATEMENT
字段的值相同。
如何验证
如果您怀疑 QUERY_SQL
字段的值不正确,可以采取以下步骤进行验证:
检查 SQL 语句 :确保您提交的 SQL 语句确实包含参数。
查看执行计划 :使用 EXPLAIN
语句查看 SQL 语句的执行计划,确认是否进行了参数化。
日志分析 :使用 obdiag
工具收集诊断信息,分析日志文件,查看 SQL 语句的执行过程。
示例
假设您有一个 SQL 语句:
SELECT * FROM test_pymysql WHERE id = 1;
在 GV$OB_PLAN_CACHE_PLAN_STAT
视图中,STATEMENT
和 QUERY_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]
检索到的文档如下:
PyMySQL 连接 OceanBase 数据库示例程序
注释
V$SQL_WORKAREA_ACTIVE
GV$SQL_WORKAREA_ACTIVE
(小助手的答复已结束,如未能解决您的问题,请继续提问并等待其他同学的回复,谢谢!)
奇怪,之前查 GV$OB_PLAN_CACHE_PLAN_STAT
视图中的 QUERY_SQL
字段值都是实际执行的SQL啊
我觉得关于query_sql什么时候是参数化应该说明下,之前查都是标准的SQL语句,这次查是参数化形式,肯定是有原因的,要么就是BUG
辞霜
2024 年11 月 1 日 17:40
#15
这边查看官方文档中的说明 社区版最早3.1版本的gv$plan_cache_plan_stat
也是说明了是参数化的sql,你之前查询的原sql有例子保存么
https://www.oceanbase.com/docs/community-observer-cn-10000000000016896
1 个赞
当 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 最佳实践文档-分布式数据库使用文档