询问一个SQL的执行计划问题

【 生产环境 】
【 OB 】
【 4.2.1.7 】
【问题描述】
SQL1:
SELECT
*
FROM
TABLE
WHERE
did = xxx or phone= xxx
and action in (‘xx’,‘xx’)
and event_time >= xx
and event_time <= xx

SQL2:
SELECT
*
FROM
TABLE
WHERE
(did = xxx or phone= xxx)
and action in (‘xx’,‘xx’)
and event_time >= xx
and event_time <= xx

这两个SQL为什么执行计划不一样啊,执行第一个会不会有歧义呢

OceanBase 社区已接收您的帖子,正在跟进中。

and 和 or 同级别时 and 的优先级高于 or 。

两个的语义不一样,and和or有优先级的说法。第一个SQL会被翻译成:FROM
TABLE
WHERE
(did = xxx) or (phone= xxx
and action in (‘xx’,‘xx’)
and event_time >= xx
and event_time <= xx)
所以两个是不同的

2 个赞

问题1:SQL1和SQL2的执行计划为什么不一样?
答:and优先级高于or,SQL1和SQL2虽然结果一致,但是SQL不同,执行计划不一致属于正常现象

问题2:同文本同参数同约束的SQL为什么多次执行会出现执行计划不一样的情况?
答:这种情况很少见,要么是计划淘汰了重新生成计划,要么是开了弱读在同机器上缓存了不同的计划,还有可能计划淘汰后重新生成,但在同一时间内针对同一个具体文本库内存在两种不同的计划是不符合预期的
a.查看读策略:show proxyconfig like “%obproxy_read_consistency%”;
b.查看执行计划变化情况
select HIT_COUNT,PLAN_ID,SQL_ID,OUTLINE_ID,FIRST_LOAD_TIME,LAST_ACTIVE_TIME from GV$OB_PLAN_CACHE_PLAN_STAT
where tenant_id= 1016 and query_sql != ‘’
and query_sql like ‘SELECT * FROM xxxx WHERE%’
limit 20

这里新生成了执行计划 13398,原因是和计划 9803的具体SQL文本不一致(did取值不一样),是正常的重新生成了计划重新命中,符合预期

问题3:如图,需要的逻辑是 did action event_time OR dxm_phone action event_time 但是优化器认为是did OR dxm_phone action event_time,是这样吗?

答:走不走union or 展开完全是优化器代价选择,没展开只能用到其中一个索引,是正常的

问题4:动态采样的作用
答:一部分计划路径会动态采样增加一些统计信息的来源,方便更优的生成计划
查询方式:show variables like “%dynamic%”;

问题5:OB里支持online新增索引吗?
online ddl 不影响读写,但本质上是后台新建了一份数据副本,等到合适的时机替换一下,不会产生锁表锁行现象,未重建完成前读写只能访问到原快照,切换的时机可能存在轻微的抖动,但由于新增了一个集群的后台写作业,一般都是建议业务低谷操作

问题6:假如加索引到一半遇到问题,我们终止掉了,会自动回滚吗?
会的,事务没完成,但后台存储层可能新增了很多无效的数据,需要手动清理?

1 个赞

是两个同的sql,执行计划自然也不同