执行计划突变的验证

2024年 5月 7日 35.8k 0

背景:

因为前期遇到过执行计划突变导致的集群问题,我们做了一些监控及手段,我对于这些现象和原理简单验证和分享一下。

扩展分享:

1. ob在4.0增加了cursor_sharing参数

该参数主要是为了用于判断处理 SQL 时是否进行参数化。OB在前期版本默认把一些常量会做参数化处理,这样多个不同参数的sql可以复用执行计划,减少解析的代价,但是对于数据倾斜的情况会出现走错执行计划的情况,暂时这篇分享不详细探究了。也与白鳝老师探讨请教了下,可以参考白鳝老师的公众号。链接:https://mp.weixin.qq.com/s/z4fk7PmA7uam2Jpj-A4PXw

2. ob在4.x提升对于pl的一些优化

我做了个很简单的测试,因为本篇不是主要探究这个事情,简单介绍下让大家知道,在ob的3.x版本可以理解是有两套sql引擎,一套火山模型一套向量模型(4.x只有一套代码使用向量引擎,在3.x做过度),所以大部分pl在3.x还是走的老引擎,sql有些触发bug的情况下也会走到老引擎(这个问题很少见在3.x前期版本遇到过),对于匿名块可以看到sql aduit是没有sqlid的,plan cache里也查不到,是不缓存的,也就是匿名块每次都是硬解析。当然我在4.2.1版本测试plan cache里也是没有缓存的,但是已经有sqlid了,应该后续产品会把这块完善。

obclient [ACCOUNT]> DECLARE    query_2 VARCHAR2(200) := 'SELECT * from OB_PLAN_TEST1 where DDID = :x';    a number :=1;   BEGIN     while a=1 LOOP execute immediate query_2 USING  '370623.122717135116785630990292275519114'; a:=a+1; DBMS_OUTPUT.PUT_LINE(a||'完成');     end loop; END;/
Query OK, 1 row affected (0.058 sec)

2完成
obclient [ACCOUNT]> DECLARE    query_2 VARCHAR2(200) := 'SELECT * from OB_PLAN_TEST1 where DDID = :x';    a number :=1;   BEGIN     while a=1 LOOP execute immediate query_2 USING  '370623.122717135116785630990292275519114'; a:=a+1; DBMS_OUTPUT.PUT_LINE(a||'完成');     end loop; END;/
Query OK, 1 row affected (0.053 sec)

2完成



MySQL [oceanbase]> select /*+parallel(32)*/ sql_id,usec_to_time(request_time),svr_ip,plan_id,params_value,query_sql,plan_type,ELAPSED_TIME from gv$ob_sql_audit where query_sql like '%DECLARE%' order by request_time limit 50;
+----------------------------------+----------------------------+----------------+---------+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+--------------+
| sql_id                           | usec_to_time(request_time) | svr_ip         | plan_id | params_value | query_sql                                                                                                                                                                                                                                                                 | plan_type | ELAPSED_TIME |
+----------------------------------+----------------------------+----------------+---------+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+--------------+
| D62BAB1A05D83614534EF5260991A487 | 2023-12-04 14:44:01.209444 | 172.16.100.137 |       0 |              | DECLARE    query_2 VARCHAR2(200) := 'SELECT * from OB_PLAN_TEST1 where DDID = :x';    a number :=1;   BEGIN     while a=1 LOOP execute immediate query_2 USING  '370623.122717135116785630990292275519114'; a:=a+1; DBMS_OUTPUT.PUT_LINE(a||'完成');     end loop; END;   |         0 |        56042 |
| D62BAB1A05D83614534EF5260991A487 | 2023-12-04 14:44:02.073641 | 172.16.100.137 |       0 |              | DECLARE    query_2 VARCHAR2(200) := 'SELECT * from OB_PLAN_TEST1 where DDID = :x';    a number :=1;   BEGIN     while a=1 LOOP execute immediate query_2 USING  '370623.122717135116785630990292275519114'; a:=a+1; DBMS_OUTPUT.PUT_LINE(a||'完成');     end loop; END;   |         0 |        51807 |
+----------------------------------+----------------------------+----------------+---------+--------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------+--------------+
2 rows in set (0.01 sec)

obclient [ACCOUNT]> select  * from  gv$ob_plan_cache_plan_stat where query_id ='D62BAB1A05D83614534EF5260991A487';
Empty set (0.057 sec)

单表的执行计划突变及验证过程:

一般单表计划改变,都是因为plan_cache被刷掉后,sql重新解析,因为各种原因(如统计信息失效或者对于这条sql代价比较低)生成了差的执行计划,后续sql会复用该计划导致负载异常。ps:ob每晚会定时合并,会收集存储引擎级别的统计信息,如果手工收集了统计信息,优先级会高于自动收集的统计信息。

--生成测试数据
CREATE TABLE "OB_PLAN_TEST1" (
   "DDID" VARCHAR2(40)  NOT NULL ENABLE,
   "DDNAME" VARCHAR2(128),
   "CCCID" VARCHAR2(32)  NOT NULL ENABLE,
   "FFFF" NUMBER(3),
   "DDDDD" NUMBER(1),
   "STATUSDATE" DATE,
   "FS" VARCHAR2(1024)
 );
 
 
declare
jid number :=0;
begin
loop  
    jid := jid+1;
    insert into OB_PLAN_TEST1 values( dbms_random.value(1,500000),'cd','DD'||jid,2,1,sysdate,'sdas');
    --commit;
   if  jid >2000000 then
   commit;
   exit;
   end if;
  end loop;
end;
/

commit;

call dbms_stats.gather_table_stats('ACCOUNT','OB_PLAN_TEST1',granularity=>'ALL',method_opt=>'FOR ALL COLUMNS SIZE 128');

create index idx_OB_PLAN_TEST1 on OB_PLAN_TEST1(DDID);

update OB_PLAN_TEST1 set DDID=1 where rownum < 500000;
commit;

--数据库版本(经测试在4.2.1版本仍然存在该问题)
observer (OceanBase 3.2.3.3)

REVISION: 109010012023072721-72e06032a278e9939718a67c2512da1e9f94775a
BUILD_BRANCH: HEAD
BUILD_TIME: Jul 27 2023 22:10:46
BUILD_FLAGS: RelWithDebInfo
BUILD_INFO: 

Copyright (c) 2011-2020 Alipay Inc.
--验证过程
obclient> select  *  from OB_PLAN_TEST1 where DDID<> 1 and rownum=1;
+------------------------------------------+--------+---------+------+-------+---------------------+------+
| DDID                                     | DDNAME | CCCID   | FFFF | DDDDD | STATUSDATE          | FS   |
+------------------------------------------+--------+---------+------+-------+---------------------+------+
| 153477.033350996877667355771590526403007 | cd     | DD50000 |    2 |     1 | 2023-11-29 17:15:28 | sdas |
+------------------------------------------+--------+---------+------+-------+---------------------+------+
1 row in set (0.06 sec)
select count(*) from OB_PLAN_TEST1 ;
select count(*) from OB_PLAN_TEST1 where DDID='1';
select count(*) from OB_PLAN_TEST1 where DDID='153477.033350996877667355771590526403007';
explain select * from OB_PLAN_TEST1 where DDID='1'\G
explain select * from OB_PLAN_TEST1 where DDID='153477.033350996877667355771590526403007'\G




obclient> select count(*) from OB_PLAN_TEST1 ;
+----------+
| COUNT(*) |
+----------+
|   200001 |
+----------+
1 row in set (0.11 sec)
--DDID='1'为大账号
obclient> select count(*) from OB_PLAN_TEST1 where DDID='1';
+----------+
| COUNT(*) |
+----------+
|    49999 |
+----------+
1 row in set (0.04 sec)
--DDID='153477.033350996877667355771590526403007'为小账号
obclient> select count(*) from OB_PLAN_TEST1 where DDID='153477.033350996877667355771590526403007';
+----------+
| COUNT(*) |
+----------+
|        1 |
+----------+
1 row in set (0.00 sec)

--可以看到explain执行计划是对的,大账号走全表扫描,小账号走索引扫描
obclient> explain select * from OB_PLAN_TEST1 where DDID='1'\G
*************************** 1. row ***************************
Query Plan: =============================================
|ID|OPERATOR  |NAME         |EST. ROWS|COST |
---------------------------------------------
|0 |TABLE SCAN|OB_PLAN_TEST1|59629    |78575|
=============================================

Outputs & filters: 
-------------------------------------
  0 - output([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), filter([OB_PLAN_TEST1.DDID = ?]), 
      access([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), partitions(p0)

1 row in set (0.01 sec)

obclient> explain select * from OB_PLAN_TEST1 where DDID='153477.033350996877667355771590526403007'\G
*************************** 1. row ***************************
Query Plan: ===============================================================
|ID|OPERATOR  |NAME                            |EST. ROWS|COST|
---------------------------------------------------------------
|0 |TABLE SCAN|OB_PLAN_TEST1(IDX_OB_PLAN_TEST1)|1        |4   |
===============================================================

Outputs & filters: 
-------------------------------------
  0 - output([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), filter(nil), 
      access([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), partitions(p0)

1 row in set (0.00 sec)

--清空plancache和sqlaudit,使接下来sql重新解析,方便查看
MySQL [oceanbase]> alter system flush plan cache global;
Query OK, 0 rows affected (0.10 sec)

MySQL [oceanbase]> alter system flush sql audit global;
Query OK, 0 rows affected (0.20 sec)


--分别执行大小账号的查询
obclient> select * from OB_PLAN_TEST1 where DDID='1';
.
.
49999 rows in set (0.29 sec)



obclient> select * from OB_PLAN_TEST1 where DDID='153477.033350996877667355771590526403007';
+------------------------------------------+--------+---------+------+-------+---------------------+------+
| DDID                                     | DDNAME | CCCID   | FFFF | DDDDD | STATUSDATE          | FS   |
+------------------------------------------+--------+---------+------+-------+---------------------+------+
| 153477.033350996877667355771590526403007 | cd     | DD50000 |    2 |     1 | 2023-11-29 17:15:28 | sdas |
+------------------------------------------+--------+---------+------+-------+---------------------+------+
1 row in set (0.14 sec)


MySQL [oceanbase]> select  sql_id,query_sql from  gv$sql_audit  where query_sql like '%select * from OB_PLAN_TEST1 where DDID%' and  query_sql not like '%query_sql%' and query_sql not like '%explain%'\G
*************************** 1. row ***************************
   sql_id: CBD4BDA406ED0B73D47864A5739C44CE
query_sql: select * from OB_PLAN_TEST1 where DDID='1'
*************************** 2. row ***************************
   sql_id: CBD4BDA406ED0B73D47864A5739C44CE
query_sql: select * from OB_PLAN_TEST1 where DDID='153477.033350996877667355771590526403007'
2 rows in set (2.61 sec)


MySQL [oceanbase]> select /*+parallel(32)*/ sql_id,usec_to_time(request_time),svr_ip,plan_id,params_value,query_sql,plan_type from gv$sql_audit where sql_id='CBD4BDA406ED0B73D47864A5739C44CE' order by request_time limit 10;
+----------------------------------+----------------------------+-------------+---------+--------------+-----------------------------------------------------------------------------------+-----------+
| sql_id                           | usec_to_time(request_time) | svr_ip      | plan_id | params_value | query_sql                                                                         | plan_type |
+----------------------------------+----------------------------+-------------+---------+--------------+-----------------------------------------------------------------------------------+-----------+
| CBD4BDA406ED0B73D47864A5739C44CE | 2023-11-29 17:22:01.244336 | 111.11.11.1 | 3081629 |              | select * from OB_PLAN_TEST1 where DDID='1'                                        |         1 |
| CBD4BDA406ED0B73D47864A5739C44CE | 2023-11-29 17:22:28.842721 | 111.11.11.1 | 3081629 |              | select * from OB_PLAN_TEST1 where DDID='153477.033350996877667355771590526403007' |         1 |
+----------------------------------+----------------------------+-------------+---------+--------------+-----------------------------------------------------------------------------------+-----------+
2 rows in set (0.87 sec)
--可以看到最终小账号也复用了全表扫描的执行计划
MySQL [oceanbase]> select plan_id, operator, name, rows, cost from gv$plan_cache_plan_explain where tenant_id=1005 and ip='111.11.11.1' and port=2882 and plan_id=3081629;
+---------+----------------+---------------+-------+-------+
| plan_id | operator       | name          | rows  | cost  |
+---------+----------------+---------------+-------+-------+
| 3081629 | PHY_TABLE_SCAN | OB_PLAN_TEST1 | 59629 | 78574 |
+---------+----------------+---------------+-------+-------+
1 row in set (0.00 sec)

该问题其实可以使用ACS解决,但是ob的acs在实验室测试阶段引入了很多问题,现在还没有上线

分区表的执行计划突变及验证过程:

分区表相关的计划突变其实与单表类似,但是后来ob对这块做了相关优化,所以我们单独做个测试。

--生成测试数据
CREATE TABLE "OB_PLAN_TEST1" (
   "DDID" VARCHAR2(40)  NOT NULL ENABLE,
   "DDNAME" VARCHAR2(128),
   "CCCID" VARCHAR2(32)  NOT NULL ENABLE,
   "FFFF" NUMBER(3),
   "DDDDD" NUMBER(1),
   "STATUSDATE" DATE,
   "FS" VARCHAR2(1024),
   CITY NUMBER(5) NOT NULL ENABLE
 )partition by range("CITY")
(partition P_100 values less than (200),
partition P_200 values less than (300),
partition P_300 values less than (400),
partition P_400 values less than (500));
 

declare
jid number :=0;
begin
loop  
    jid := jid+1;
    insert into OB_PLAN_TEST1 values( dbms_random.value(1,500000),'cd','DD'||jid,2,1,sysdate,'sdas',400);
    --commit;
   if  jid >200000 then
   commit;
   exit;
   end if;
  end loop;
end;
/
insert into OB_PLAN_TEST1 values( dbms_random.value(1,500000),'cd','DD'||'www',2,1,sysdate,'sdas',300);
commit;

select  CITY,count(*) from  OB_PLAN_TEST1 group by CITY;
create index idx_OB_PLAN_TEST1 on OB_PLAN_TEST1(DDID) local;
call dbms_stats.gather_table_stats('ACCOUNT','OB_PLAN_TEST1',granularity=>'ALL',method_opt=>'FOR ALL COLUMNS SIZE 128');


--3.2.3的前期版本
observer (OceanBase 3.2.3.3)

REVISION: 109010012023072721-72e06032a278e9939718a67c2512da1e9f94775a
BUILD_BRANCH: HEAD
BUILD_TIME: Jul 27 2023 22:10:46
BUILD_FLAGS: RelWithDebInfo
BUILD_INFO: 

Copyright (c) 2011-2020 Alipay Inc.

--测试过程,分区300为小分区,分区400为大分区
 obclient> select  CITY,count(*) from  OB_PLAN_TEST1 group by CITY;
+------+----------+
| CITY | COUNT(*) |
+------+----------+
|  300 |        1 |
|  400 |   200001 |
+------+----------+
2 rows in set (0.20 sec)
obclient> select  *  from OB_PLAN_TEST1 where CITY=300;
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
| DDID                                     | DDNAME | CCCID | FFFF | DDDDD | STATUSDATE          | FS   | CITY |
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
| 438916.090508550075909523829593371519369 | cd     | DDwww |    2 |     1 | 2023-12-01 16:41:23 | sdas |  300 |
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
1 row in set (0.03 sec)

obclient> select  *  from OB_PLAN_TEST1 where CITY=400 and rownum=1;
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
| DDID                                     | DDNAME | CCCID | FFFF | DDDDD | STATUSDATE          | FS   | CITY |
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
| 226565.232611556997487602769478763788588 | cd     | DD1   |    2 |     1 | 2023-12-01 16:38:54 | sdas |  400 |
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
1 row in set (0.02 sec)



explain select * from OB_PLAN_TEST1 where DDID='438916.090508550075909523829593371519369' and  CITY=300\G
explain select * from OB_PLAN_TEST1 where DDID='226565.232611556997487602769478763788588' and  CITY=400\G


--可以看到explain执行计划是对的,小分区走全表扫描,大分区走索引扫描
obclient> explain select * from OB_PLAN_TEST1 where DDID='438916.090508550075909523829593371519369' and  CITY=300\G
*************************** 1. row ***************************
Query Plan: ============================================
|ID|OPERATOR  |NAME         |EST. ROWS|COST|
--------------------------------------------
|0 |TABLE SCAN|OB_PLAN_TEST1|1        |1   |
============================================

Outputs & filters: 
-------------------------------------
  0 - output([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS], [OB_PLAN_TEST1.CITY]), filter([OB_PLAN_TEST1.DDID = ?]), 
      access([OB_PLAN_TEST1.CITY], [OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), partitions(p2)

1 row in set (0.00 sec)

obclient> explain select * from OB_PLAN_TEST1 where DDID='226565.232611556997487602769478763788588' and  CITY=400\G
*************************** 1. row ***************************
Query Plan: ===============================================================
|ID|OPERATOR  |NAME                            |EST. ROWS|COST|
---------------------------------------------------------------
|0 |TABLE SCAN|OB_PLAN_TEST1(IDX_OB_PLAN_TEST1)|1        |4   |
===============================================================

Outputs & filters: 
-------------------------------------
  0 - output([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS], [OB_PLAN_TEST1.CITY]), filter(nil), 
      access([OB_PLAN_TEST1.CITY], [OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), partitions(p3)

1 row in set (0.00 sec)

--清空plancache和sqlaudit
alter system flush plan cache global;
alter system flush sql audit global;



MySQL [oceanbase]> select  sql_id,query_sql from  gv$sql_audit  where query_sql like '%select * from OB_PLAN_TEST1 where DDID=%' and  query_sql not like '%query_sql%' and query_sql not like '%explain%'\G
*************************** 1. row ***************************
   sql_id: 2FA089055677A69C67B9E4F816A8D9EF
query_sql: select * from OB_PLAN_TEST1 where DDID='438916.090508550075909523829593371519369' and  CITY=300
*************************** 2. row ***************************
   sql_id: 2FA089055677A69C67B9E4F816A8D9EF
query_sql: select * from OB_PLAN_TEST1 where DDID='226565.232611556997487602769478763788588' and  CITY=400
2 rows in set (0.17 sec)

MySQL [oceanbase]> select /*+parallel(32)*/ sql_id,usec_to_time(request_time),svr_ip,plan_id,params_value,query_sql,plan_type,ELAPSED_TIME from gv$sql_audit where sql_id='2FA089055677A69C67B9E4F816A8D9EF' order by request_time limit 50;
+----------------------------------+----------------------------+-------------+---------+--------------+-------------------------------------------------------------------------------------------------+-----------+--------------+
| sql_id                           | usec_to_time(request_time) | svr_ip      | plan_id | params_value | query_sql                                                                                       | plan_type | ELAPSED_TIME |
+----------------------------------+----------------------------+-------------+---------+--------------+-------------------------------------------------------------------------------------------------+-----------+--------------+
| 2FA089055677A69C67B9E4F816A8D9EF | 2023-12-01 16:48:50.012069 | 134.84.16.2 |    7364 |              | select * from OB_PLAN_TEST1 where DDID='438916.090508550075909523829593371519369' and  CITY=300 |         1 |         1706 |
| 2FA089055677A69C67B9E4F816A8D9EF | 2023-12-01 16:48:59.847533 | 134.84.16.2 |    7364 |              | select * from OB_PLAN_TEST1 where DDID='226565.232611556997487602769478763788588' and  CITY=400 |         1 |       144013 |
+----------------------------------+----------------------------+-------------+---------+--------------+-------------------------------------------------------------------------------------------------+-----------+--------------+
2 rows in set (0.07 sec)
--可以看到大分区账号复用了小分区账号的执行计划,走了错误的执行计划
MySQL [oceanbase]> select plan_id, operator, name, rows, cost from gv$plan_cache_plan_explain where tenant_id=1005 and ip='134.84.16.2' and port=2882 and plan_id=7364;
+---------+----------------+---------------+------+------+
| plan_id | operator       | name          | rows | cost |
+---------+----------------+---------------+------+------+
|    7364 | PHY_TABLE_SCAN | OB_PLAN_TEST1 |    1 |    0 |
+---------+----------------+---------------+------+------+
1 row in set (0.01 sec)



--3.2.3后期版本引入了两个参数
observer (OceanBase 3.2.3.3)

REVISION: 110020012023110315-55cf8deebb891498d8c87ab742cde4809c018219
BUILD_BRANCH: HEAD
BUILD_TIME: Nov  3 2023 15:27:14
BUILD_FLAGS: RelWithDebInfo
BUILD_INFO: 

Copyright (c) 2011-2020 Alipay Inc.

<><><><><><><>
##############################
--根据分区分裂执行计划
MySQL [oceanbase]> alter system set _enable_partition_level_acs = True tenant='cc1cs';
Query OK, 0 rows affected (0.03 sec)
--索引代价评估(该参数在这个实验中先不介绍了)
MySQL [oceanbase]>  alter system set optimizer_index_cost_adj =1 tenant='cc1cs';
Query OK, 0 rows affected (0.02 sec)

MySQL [oceanbase]> select  * from __all_virtual_tenant_parameter_info  where name like '%enable_partition_level_acs%';
+-----------+-------+----------+-------------+----------+-----------------------------+-----------+-------+-------------------------------+---------+--------+---------+-------------------+
| tenant_id | zone  | svr_type | svr_ip      | svr_port | name                        | data_type | value | info                          | section | scope  | source  | edit_level        |
+-----------+-------+----------+-------------+----------+-----------------------------+-----------+-------+-------------------------------+---------+--------+---------+-------------------+
|         1 | zone1 | observer | 122.22.22.8 |     2882 | _enable_partition_level_acs | NULL      | True  | enable acs in partition level | TENANT  | TENANT | DEFAULT | DYNAMIC_EFFECTIVE |
|      1003 | zone1 | observer | 122.22.22.9 |     2882 | _enable_partition_level_acs | NULL      | True  | enable acs in partition level | TENANT  | TENANT | DEFAULT | DYNAMIC_EFFECTIVE |
|         1 | zone1 | observer | 122.22.22.8 |     2882 | _enable_partition_level_acs | NULL      | True  | enable acs in partition level | TENANT  | TENANT | DEFAULT | DYNAMIC_EFFECTIVE |
|      1003 | zone1 | observer | 122.22.22.8 |     2882 | _enable_partition_level_acs | NULL      | True  | enable acs in partition level | TENANT  | TENANT | DEFAULT | DYNAMIC_EFFECTIVE |
+-----------+-------+----------+-------------+----------+-----------------------------+-----------+-------+-------------------------------+---------+--------+---------+-------------------+
4 rows in set (0.06 sec)
MySQL [oceanbase]> select  * from __all_virtual_tenant_parameter_info  where name like '%optimizer_index_cost_adj%';
+-----------+-------+----------+-------------+----------+--------------------------+-----------+-------+------------------------------+---------+--------+---------+-------------------+
| tenant_id | zone  | svr_type | svr_ip      | svr_port | name                     | data_type | value | info                         | section | scope  | source  | edit_level        |
+-----------+-------+----------+-------------+----------+--------------------------+-----------+-------+------------------------------+---------+--------+---------+-------------------+
|         1 | zone1 | observer | 122.22.22.8 |     2882 | optimizer_index_cost_adj | NULL      | 0     | adjust costing of index scan | TENANT  | TENANT | DEFAULT | DYNAMIC_EFFECTIVE |
|      1003 | zone1 | observer | 122.22.22.8 |     2882 | optimizer_index_cost_adj | NULL      | 1     | adjust costing of index scan | TENANT  | TENANT | DEFAULT | DYNAMIC_EFFECTIVE |
|         1 | zone1 | observer | 122.22.22.9 |     2882 | optimizer_index_cost_adj | NULL      | 0     | adjust costing of index scan | TENANT  | TENANT | DEFAULT | DYNAMIC_EFFECTIVE |
|      1003 | zone1 | observer | 122.22.22.9 |     2882 | optimizer_index_cost_adj | NULL      | 1     | adjust costing of index scan | TENANT  | TENANT | DEFAULT | DYNAMIC_EFFECTIVE |
+-----------+-------+----------+-------------+----------+--------------------------+-----------+-------+------------------------------+---------+--------+---------+-------------------+
4 rows in set (0.06 sec)

##########################
--验证过程与上面一致
obclient> select  CITY,count(*) from  OB_PLAN_TEST1 group by CITY;
+------+----------+
| CITY | COUNT(*) |
+------+----------+
|  300 |        1 |
|  400 |   200001 |
+------+----------+
2 rows in set (0.20 sec)

obclient> select  *  from OB_PLAN_TEST1 where CITY=300;
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
| DDID                                     | DDNAME | CCCID | FFFF | DDDDD | STATUSDATE          | FS   | CITY |
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
| 344423.097813308868309580547313255124084 | cd     | DDwww |    2 |     1 | 2023-12-01 16:52:32 | sdas |  300 |
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
1 row in set (0.04 sec)

obclient> select  *  from OB_PLAN_TEST1 where CITY=400 and rownum=1;
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
| DDID                                     | DDNAME | CCCID | FFFF | DDDDD | STATUSDATE          | FS   | CITY |
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
| 119548.132022013705188211994065427849317 | cd     | DD1   |    2 |     1 | 2023-12-01 16:39:50 | sdas |  400 |
+------------------------------------------+--------+-------+------+-------+---------------------+------+------+
1 row in set (0.06 sec)

explain select * from OB_PLAN_TEST1 where DDID='344423.097813308868309580547313255124084' and  CITY=300\G
explain select * from OB_PLAN_TEST1 where DDID='119548.132022013705188211994065427849317' and  CITY=400\G


obclient> explain select * from OB_PLAN_TEST1 where DDID='344423.097813308868309580547313255124084' and  CITY=300\G
*************************** 1. row ***************************
Query Plan: ============================================
|ID|OPERATOR  |NAME         |EST. ROWS|COST|
--------------------------------------------
|0 |TABLE SCAN|OB_PLAN_TEST1|1        |1   |
============================================

Outputs & filters: 
-------------------------------------
  0 - output([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS], [OB_PLAN_TEST1.CITY]), filter([OB_PLAN_TEST1.DDID = ?]), 
      access([OB_PLAN_TEST1.CITY], [OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), partitions(p2)

1 row in set (0.01 sec)

obclient> explain select * from OB_PLAN_TEST1 where DDID='119548.132022013705188211994065427849317' and  CITY=400\G
*************************** 1. row ***************************
Query Plan: =========================================================================
|ID|OPERATOR            |NAME                            |EST. ROWS|COST|
-------------------------------------------------------------------------
|0 |EXCHANGE IN REMOTE  |                                |1        |6   |
|1 | EXCHANGE OUT REMOTE|                                |1        |4   |
|2 |  TABLE SCAN        |OB_PLAN_TEST1(IDX_OB_PLAN_TEST1)|1        |4   |
=========================================================================

Outputs & filters: 
-------------------------------------
  0 - output([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS], [OB_PLAN_TEST1.CITY]), filter(nil)
  1 - output([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS], [OB_PLAN_TEST1.CITY]), filter(nil)
  2 - output([OB_PLAN_TEST1.CITY], [OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), filter(nil), 
      access([OB_PLAN_TEST1.CITY], [OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), partitions(p3)

1 row in set (0.01 sec)



MySQL [oceanbase]> select  sql_id,query_sql from  gv$sql_audit  where query_sql like '%select * from OB_PLAN_TEST1 where DDID=%' and  query_sql not like '%query_sql%' and query_sql not like '%explain%'\G
*************************** 1. row ***************************
   sql_id: 2FA089055677A69C67B9E4F816A8D9EF
query_sql: select * from OB_PLAN_TEST1 where DDID='344423.097813308868309580547313255124084' and  CITY=300
*************************** 2. row ***************************
   sql_id: 2FA089055677A69C67B9E4F816A8D9EF
query_sql: select * from OB_PLAN_TEST1 where DDID='119548.132022013705188211994065427849317' and  CITY=400
2 rows in set (0.04 sec)

MySQL [oceanbase]> select /*+parallel(32)*/ sql_id,usec_to_time(request_time),svr_ip,plan_id,params_value,query_sql,plan_type,ELAPSED_TIME from gv$sql_audit where sql_id='2FA089055677A69C67B9E4F816A8D9EF' order by request_time limit 50;
+----------------------------------+----------------------------+-------------+---------+--------------+-------------------------------------------------------------------------------------------------+-----------+--------------+
| sql_id                           | usec_to_time(request_time) | svr_ip      | plan_id | params_value | query_sql                                                                                       | plan_type | ELAPSED_TIME |
+----------------------------------+----------------------------+-------------+---------+--------------+-------------------------------------------------------------------------------------------------+-----------+--------------+
| 2FA089055677A69C67B9E4F816A8D9EF | 2023-12-01 16:55:27.879506 | 122.22.22.9 |  110392 |              | select * from OB_PLAN_TEST1 where DDID='344423.097813308868309580547313255124084' and  CITY=300 |         1 |         2915 |
| 2FA089055677A69C67B9E4F816A8D9EF | 2023-12-01 16:55:38.931865 | 122.22.22.9 |  110398 |              | select * from OB_PLAN_TEST1 where DDID='119548.132022013705188211994065427849317' and  CITY=400 |         2 |         9502 |
+----------------------------------+----------------------------+-------------+---------+--------------+-------------------------------------------------------------------------------------------------+-----------+--------------+
2 rows in set (0.05 sec)

--可以看到开启分区分裂计划的参数后生成了两个计划,两个sql都走了正确的计划
MySQL [oceanbase]> select plan_id, operator, name, rows, cost from gv$plan_cache_plan_explain where tenant_id=1003 and ip='122.22.22.9' and port=2882 and plan_id=110392;
+---------+----------------+---------------+------+------+
| plan_id | operator       | name          | rows | cost |
+---------+----------------+---------------+------+------+
|  110392 | PHY_TABLE_SCAN | OB_PLAN_TEST1 |    1 |    0 |
+---------+----------------+---------------+------+------+
1 row in set (0.01 sec)

MySQL [oceanbase]> select plan_id, operator, name, rows, cost from gv$plan_cache_plan_explain where tenant_id=1003 and ip='122.22.22.9' and port=2882 and plan_id=110398;
+---------+----------------------+----------------------------------+------+------+
| plan_id | operator             | name                             | rows | cost |
+---------+----------------------+----------------------------------+------+------+
|  110398 | PHY_DIRECT_RECEIVE   | NULL                             |    1 |    5 |
|  110398 |  PHY_DIRECT_TRANSMIT | NULL                             |    1 |    3 |
|  110398 |   PHY_TABLE_SCAN     | OB_PLAN_TEST1(IDX_OB_PLAN_TEST1) |    1 |    3 |
+---------+----------------------+----------------------------------+------+------+
3 rows in set (0.00 sec)

因为我在4.2.1版本上没有找到该参数,那验证下实际表现如何

--版本信息
observer (OceanBase 4.2.1.1)

REVISION: 101010022023110921-5d0b2ec58d7661e382f65d3753b65f3a914f89ec
BUILD_BRANCH: HEAD
BUILD_TIME: Nov  9 2023 21:27:01
BUILD_FLAGS: RelWithDebInfo
BUILD_INFO: 

Copyright (c) 2011-present OceanBase Inc.

--数据分布,与上面实验一样,大小分区
obclient [ACCOUNT]> select  CITY,count(*) from  OB_PLAN_TEST1 group by CITY;
+------+----------+
| CITY | COUNT(*) |
+------+----------+
|  300 |        1 |
|  400 |   200001 |
+------+----------+
2 rows in set (0.305 sec)
obclient [ACCOUNT]> select  *  from OB_PLAN_TEST1 where CITY=300;
+------------------------------------------+--------+-------+------+-------+------------+------+------+
| DDID                                     | DDNAME | CCCID | FFFF | DDDDD | STATUSDATE | FS   | CITY |
+------------------------------------------+--------+-------+------+-------+------------+------+------+
| 298225.370594538611501792855979394021071 | cd     | DDwww |    2 |     1 | 01-DEC-23  | sdas |  300 |
+------------------------------------------+--------+-------+------+-------+------------+------+------+
1 row in set (0.083 sec)

obclient [ACCOUNT]> select  *  from OB_PLAN_TEST1 where CITY=400 and rownum=1;
+------------------------------------------+--------+-------+------+-------+------------+------+------+
| DDID                                     | DDNAME | CCCID | FFFF | DDDDD | STATUSDATE | FS   | CITY |
+------------------------------------------+--------+-------+------+-------+------------+------+------+
| 269826.523111291697766623468575040129842 | cd     | DD1   |    2 |     1 | 01-DEC-23  | sdas |  400 |
+------------------------------------------+--------+-------+------+-------+------------+------+------+
1 row in set (0.017 sec)

explain select * from OB_PLAN_TEST1 where DDID='298225.370594538611501792855979394021071' and  CITY=300;
explain select * from OB_PLAN_TEST1 where DDID='269826.523111291697766623468575040129842' and  CITY=400;

--这里不同的是,小分区也走了索引,因为代价不大,所以这个计划没有问题
obclient [ACCOUNT]> explain select * from OB_PLAN_TEST1 where DDID='298225.370594538611501792855979394021071' and  CITY=300;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan                                                                                                                                                            |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ============================================================================                                                                                          |
| |ID|OPERATOR        |NAME                            |EST.ROWS|EST.TIME(us)|                                                                                          |
| ----------------------------------------------------------------------------                                                                                          |
| |0 |TABLE RANGE SCAN|OB_PLAN_TEST1(IDX_OB_PLAN_TEST1)|1       |7           |                                                                                          |
| ============================================================================                                                                                          |
| Outputs & filters:                                                                                                                                                    |
| -------------------------------------                                                                                                                                 |
|   0 - output([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE],            |
|        [OB_PLAN_TEST1.FS], [OB_PLAN_TEST1.CITY]), filter([OB_PLAN_TEST1.CITY = 300]), rowset=16                                                                       |
|       access([OB_PLAN_TEST1.__pk_increment], [OB_PLAN_TEST1.CITY], [OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF],         |
|        [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), partitions(p2)                                                                         |
|       is_index_back=true, is_global_index=false, filter_before_indexback[false],                                                                                      |
|       range_key([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.__pk_increment]), range(298225.370594538611501792855979394021071,MIN ; 298225.370594538611501792855979394021071, |
|       MAX),                                                                                                                                                           |
|       range_cond([OB_PLAN_TEST1.DDID = cast('298225.370594538611501792855979394021071', VARCHAR2(1048576 ))])                                                         |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
15 rows in set (0.004 sec)

obclient [ACCOUNT]> explain select * from OB_PLAN_TEST1 where DDID='269826.523111291697766623468575040129842' and  CITY=400;
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan                                                                                                                                                            |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ============================================================================                                                                                          |
| |ID|OPERATOR        |NAME                            |EST.ROWS|EST.TIME(us)|                                                                                          |
| ----------------------------------------------------------------------------                                                                                          |
| |0 |TABLE RANGE SCAN|OB_PLAN_TEST1(IDX_OB_PLAN_TEST1)|1       |7           |                                                                                          |
| ============================================================================                                                                                          |
| Outputs & filters:                                                                                                                                                    |
| -------------------------------------                                                                                                                                 |
|   0 - output([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE],            |
|        [OB_PLAN_TEST1.FS], [OB_PLAN_TEST1.CITY]), filter([OB_PLAN_TEST1.CITY = 400]), rowset=16                                                                       |
|       access([OB_PLAN_TEST1.__pk_increment], [OB_PLAN_TEST1.CITY], [OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF],         |
|        [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], [OB_PLAN_TEST1.FS]), partitions(p3)                                                                         |
|       is_index_back=true, is_global_index=false, filter_before_indexback[false],                                                                                      |
|       range_key([OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.__pk_increment]), range(269826.523111291697766623468575040129842,MIN ; 269826.523111291697766623468575040129842, |
|       MAX),                                                                                                                                                           |
|       range_cond([OB_PLAN_TEST1.DDID = cast('269826.523111291697766623468575040129842', VARCHAR2(1048576 ))])                                                         |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
15 rows in set (0.017 sec)

--这里我验证了个特殊sql,传参为空,我们很多场景遇到过传参为空导致计划突变引发的性能抖动
obclient [ACCOUNT]> explain select * from OB_PLAN_TEST1 where DDID='' and  CITY=200;
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Query Plan                                                                                                                                                                       |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ==================================================================                                                                                                               |
| |ID|OPERATOR                 |NAME         |EST.ROWS|EST.TIME(us)|                                                                                                               |
| ------------------------------------------------------------------                                                                                                               |
| |0 |PX COORDINATOR           |             |200002  |1140164     |                                                                                                               |
| |1 |└─EXCHANGE OUT DISTR     |:EX10000     |200002  |797399      |                                                                                                               |
| |2 |  └─PX PARTITION ITERATOR|             |200002  |26293       |                                                                                                               |
| |3 |    └─TABLE FULL SCAN    |OB_PLAN_TEST1|200002  |26293       |                                                                                                               |
| ==================================================================                                                                                                               |
| Outputs & filters:                                                                                                                                                               |
| -------------------------------------                                                                                                                                            |
|   0 - output([INTERNAL_FUNCTION(OB_PLAN_TEST1.DDID, OB_PLAN_TEST1.DDNAME, OB_PLAN_TEST1.CCCID, OB_PLAN_TEST1.FFFF, OB_PLAN_TEST1.DDDDD, OB_PLAN_TEST1.STATUSDATE,                |
|        OB_PLAN_TEST1.FS, OB_PLAN_TEST1.CITY)]), filter(nil), startup_filter([0]), rowset=256                                                                                     |
|   1 - output([INTERNAL_FUNCTION(OB_PLAN_TEST1.DDID, OB_PLAN_TEST1.DDNAME, OB_PLAN_TEST1.CCCID, OB_PLAN_TEST1.FFFF, OB_PLAN_TEST1.DDDDD, OB_PLAN_TEST1.STATUSDATE,                |
|        OB_PLAN_TEST1.FS, OB_PLAN_TEST1.CITY)]), filter(nil), rowset=256                                                                                                          |
|       dop=1                                                                                                                                                                      |
|   2 - output([OB_PLAN_TEST1.CITY], [OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], |
|        [OB_PLAN_TEST1.FS]), filter(nil), rowset=256                                                                                                                              |
|       force partition granule                                                                                                                                                    |
|   3 - output([OB_PLAN_TEST1.CITY], [OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], |
|        [OB_PLAN_TEST1.FS]), filter(nil), rowset=256                                                                                                                              |
|       access([OB_PLAN_TEST1.CITY], [OB_PLAN_TEST1.DDID], [OB_PLAN_TEST1.DDNAME], [OB_PLAN_TEST1.CCCID], [OB_PLAN_TEST1.FFFF], [OB_PLAN_TEST1.DDDDD], [OB_PLAN_TEST1.STATUSDATE], |
|        [OB_PLAN_TEST1.FS]), partitions(p[0-3])                                                                                                                                   |
|       is_index_back=false, is_global_index=false,                                                                                                                                |
|       range_key([OB_PLAN_TEST1.__pk_increment]), range(MIN ; MAX)always true                                                                                                     |
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
24 rows in set (0.019 sec)


alter system flush plan cache global;
alter system flush sql audit global;


MySQL [oceanbase]> select  sql_id,query_sql from  gv$ob_sql_audit  where query_sql like '%select * from OB_PLAN_TEST1 where DDID=%' and  query_sql not like '%query_sql%' and query_sql not like '%explain%'\G
*************************** 1. row ***************************
   sql_id: 2FA089055677A69C67B9E4F816A8D9EF
query_sql: select * from OB_PLAN_TEST1 where DDID='' and  CITY=200
*************************** 2. row ***************************
   sql_id: 2FA089055677A69C67B9E4F816A8D9EF
query_sql: select * from OB_PLAN_TEST1 where DDID='298225.370594538611501792855979394021071' and  CITY=300
*************************** 3. row ***************************
   sql_id: 2FA089055677A69C67B9E4F816A8D9EF
query_sql: select * from OB_PLAN_TEST1 where DDID='269826.523111291697766623468575040129842' and  CITY=400
3 rows in set (0.03 sec)

--可以看到生成的是同一个sqlid,生成的计划不同
MySQL [oceanbase]> select /*+parallel(32)*/ sql_id,usec_to_time(request_time),svr_ip,plan_id,params_value,query_sql,plan_type,ELAPSED_TIME from gv$ob_sql_audit where sql_id='2FA089055677A69C67B9E4F816A8D9EF' order by request_time limit 50;
+----------------------------------+----------------------------+----------------+---------+--------------+-------------------------------------------------------------------------------------------------+-----------+--------------+
| sql_id                           | usec_to_time(request_time) | svr_ip         | plan_id | params_value | query_sql                                                                                       | plan_type | ELAPSED_TIME |
+----------------------------------+----------------------------+----------------+---------+--------------+-------------------------------------------------------------------------------------------------+-----------+--------------+
| 2FA089055677A69C67B9E4F816A8D9EF | 2023-12-01 17:24:20.618319 | 172.16.100.137 |    2185 |              | select * from OB_PLAN_TEST1 where DDID='' and  CITY=200                                         |         3 |         5143 |
| 2FA089055677A69C67B9E4F816A8D9EF | 2023-12-01 17:24:33.558938 | 172.16.100.137 |    2188 |              | select * from OB_PLAN_TEST1 where DDID='298225.370594538611501792855979394021071' and  CITY=300 |         1 |         7472 |
| 2FA089055677A69C67B9E4F816A8D9EF | 2023-12-01 17:24:40.374061 | 172.16.100.137 |    2188 |              | select * from OB_PLAN_TEST1 where DDID='269826.523111291697766623468575040129842' and  CITY=400 |         1 |       167090 |
+----------------------------------+----------------------------+----------------+---------+--------------+-------------------------------------------------------------------------------------------------+-----------+--------------+
3 rows in set (0.02 sec)

--检查可以发现计划是对的,后来sql没有复用差的计划
MySQL [oceanbase]>  select plan_id, operator, name, rows, cost from gv$ob_plan_cache_plan_explain where tenant_id=1002 and SVR_IP='172.16.100.137' and SVR_PORT=2882 and plan_id=2185;
+---------+-------------------------+---------------+--------+---------+
| plan_id | operator                | name          | rows   | cost    |
+---------+-------------------------+---------------+--------+---------+
|    2185 | PHY_PX_FIFO_COORD       | NULL          | 200002 | 1140163 |
|    2185 |  PHY_PX_REDUCE_TRANSMIT | NULL          | 200002 |  797398 |
|    2185 |   PHY_GRANULE_ITERATOR  | NULL          | 200002 |   26292 |
|    2185 |    PHY_TABLE_SCAN       | OB_PLAN_TEST1 | 200002 |   26292 |
+---------+-------------------------+---------------+--------+---------+
4 rows in set (0.01 sec)

MySQL [oceanbase]>  select plan_id, operator, name, rows, cost from gv$ob_plan_cache_plan_explain where tenant_id=1002 and SVR_IP='172.16.100.137' and SVR_PORT=2882 and plan_id=2188;
+---------+----------------+----------------------------------+------+------+
| plan_id | operator       | name                             | rows | cost |
+---------+----------------+----------------------------------+------+------+
|    2188 | PHY_TABLE_SCAN | OB_PLAN_TEST1(IDX_OB_PLAN_TEST1) |    1 |    6 |
+---------+----------------+----------------------------------+------+------+
1 row in set (0.00 sec)

结论:

1.对于这种因为复用计划导致的sql执行效率降低的情况,把plan cache中该sql的计划刷掉,重新解析下就可以。

2.4.0之后有了curso_sharing参数,可以根据业务情况决定是否使用(能否接受该类sql的硬解析),也可以解决相应的情况。

3.绑定outline固定计划,这个当然也会有一定负面影响,比如大账号走回表的代价是否可以接受。tip:对于一些多表关联的hint绑定要经过一些判断,比如a表left join b表,正常a数据量少,b数据量大,绑定走索引和nest loop的hint没有问题,但是如果a表传入大账号的时候,a表数据量大了之后效率会急剧下降,这时候可以只绑定索引的hint,让优化器自己去选择连接方式。

可以从版本的递进和发展我们也能看到ob在不断的完善,虽然仍然还存在问题,需要不断的打磨、进步,但是数据库的发展不是一蹴而就的,ob的快速迭代优化,是肉眼可以看得见的,希望ob越来越成熟、稳定吧。

行之所向,莫问远方。

相关文章

pt-kill工具的使用
pt-ioprofile工具包的使用
数据库管理-第216期 Oracle的高可用-01(20240703)
DBMS_REPAIR EXAMPLE SCRIPT WITH PARTITION
数据库事务的四大特性: ACID 
使用BBED修复损坏的SYSTEM文件头

发布评论