首批通过分布式安全可靠测评,为关键业务系统打造
OceanBase 数据库的 sql_id 和 plan_id 的稳定性介绍
更新时间:2023-11-30 12:01
OceanBase 数据库的 sql_id 和 plan_id 的稳定性很重要,因为它们是 SQL plan cache 的入口(包括 find plan detail, sql outline 绑定等)。本文主要介绍 sql_id 和 plan_id 的生成方式。
适用版本
OceanBase 数据库 V2.x 版本
sql_id
sql_id 用于唯一确定一个查询语句,它是由查询语句经过快速参数化后得到的字符串的 MD5 值,返回 128 位的哈希值。sql_id 的长度为 CHAR(32),形如 ED570339F2C856BA96008A29EDF04C74。
相同文本的 SQL 的 sql_id 总是相同的,可以通过以下脚本生成对应 SQL 的 sql_id。
import hashlib
sql_text='SELECT * FROM t1 WHERE c2 = ?'
sql_id=hashlib.md5(sql_text.encode('utf-8')).hexdigest().upper()
print(sql_id)
plan_id
plan_id 用于单个 OBServer 上唯一确定 plan_cache 中的一个plan,plan_id是一个递增的值,由 plan_cache 模块进行管理,每次新加入一个 plan 到 plan cache中时,都会为其分配一个 plan_id。plan_id 是 OBServer 启动后通过一个本地范围内的自增序列产生的值,OBServer 重启后,plan_id 会重置。plan_id 的长度为 number(38),形如 43213。plan cache 是租户间隔离的,在一台 OBServer 中,plan_id 和 tenant_id 一起决定一个执行计划。
可以通过 gv$plan_cache_plan_explain 视图查询 plan。
根据上述得到的 TENANT_ID、PLAN_ID、SVR_IP 和 SVR_PORT,查询 gv$plan_cache_plan_explain 视图。
obclient> SELECT * FROM gv$plan_cache_plan_explain WHERE tenant_id=1 AND plan_id=582518 and ip='11.1166.78.136' and port=2882;
+-----------+-----------------+------+---------+------------------+-----------------------+------+------+-------------------------------------------------------------------------------------------------------------------------------+
| TENANT_ID | IP | PORT | PLAN_ID | OPERATOR | NAME | ROWS | COST | PROPERTY |
+-----------+-----------------+------+---------+------------------+-----------------------+------+------+-------------------------------------------------------------------------------------------------------------------------------+
| 1 | xxx.xxx.xxx.xxx | 2882 | 582518 | PHY_SORT | NULL | 100 | 2418 | NULL |
| 1 | xxx.xxx.xxx.xxx | 2882 | 582518 | PHY_TABLE_SCAN | __all_virtual_sysstat | 100 | 2000 | table_rows:100000, physical_range_rows:100, logical_range_rows:100, index_back_rows:0, output_rows:100, est_method:basic_stat |
+-----------+-----------------+------+---------+------------------+-----------------------+------+------+-------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.03 sec)
与 Oracle 数据库对比
Oracle 数据库中的 sql_id 的生成方式是使用库缓冲存对象的名称计算 Hash MD5 , 得到 128 位哈希值。其中后 64 位为 sql_id,sql_id 的后32位为 hash_value。
库缓冲通过 hash_value 定位。
与 OceanBase 数据库的 sql_id 与 plan_id 生成方式不同,Oracle的 sql_id 与 SQL 的 hash_value 有关。
Oracle 数据库的 plan_hash_value 的作用类比于 OceanBase 数据库的 plan_id,虽然能绝大多数情况下识别一个 plan,但是也缺失了一些重要信息例如 mismatched predicates。
OceanBase 数据库的 plan_id 需要区分在不同 OBServer 启动生命期内的 Plan。因为OceanBase 数据库启动的前后,可能产生 sql_id、plan_id 相同的执行计划;但是由于分区迁移等情况,其实际的 Plan 结构是完全不同的。因此各种监控 console、巡检需要识别到这个不同的 Plan detail,而不是只靠 server_id+plan_id 进行查询。