问题现象
存在 (c1,c2,c3) 的索引,SQL 过滤条件中存在如下形式的过滤谓词 (c1 = ? or c1 = ?) and c2 in (?,?) and c3...。这个场景下会生成错误的 range,导致执行结果出错。
举例:(c1 = 2 or c1 = 3) and c2 in (4,5,6) and c3 = 7。
explain extended 可以看到如下 range。
(2,4,7,MIN,MIN ; 2,4,7,MAX,MAX),
(2,5,7,MIN,MIN ; 2,5,7,MAX,MAX),
(2,6,7,MIN,MIN ; 2,6,7,MAX,MAX),
(2,4,7,MIN,MIN ; 3,4,7,MAX,MAX),-- 应该是 (3,4,7,MIN,MIN ; 3,4,7,MAX,MAX)
(2,5,7,MIN,MIN ; 3,5,7,MAX,MAX),-- 应该是 (3,5,7,MIN,MIN ; 3,5,7,MAX,MAX)
(2,6,7,MIN,MIN ; 3,6,7,MAX,MAX) -- 应该是 (3,6,7,MIN,MIN ; 3,6,7,MAX,MAX)
关键诊断信息
触发条件
存在 (c1,c2,c3) 的索引,SQL 过滤条件中存在如下形式的过滤谓词 (c1 = ? or c1 = ?) and c2 in (?,?) and c3...。
事前巡检
检查是否存在上述形式的谓词和对应的索引。
事后诊断
explain 计划,检查生成的 range 中是否产生了错误的 range。
问题原因
IN 优化引入的 BUG。
问题的风险及影响
SQL 执行结果出错。
影响租户
影响 OceanBase 数据库中的 SYS 租户和 Oracle 租户以及 MySQL 租户。
影响版本
OceanBase 数据库企业版本 V3.2.3 BP6(oceanbase-3.2.3.3-106000102022111521)及之后版本、V3.2.4 GA(oceanbase-3.2.4.0-100000072022102819)及之后版本、V4.1.0 GA(oceanbase-4.1.0.0-100001122023040322)及之后版本。
解决方法
解决方法一:
升级至问题已修复版本。目前已修复的版本包括 OceanBase 数据库企业版 V3.2.3 BP8(oceanbase-3.2.3.3-108000062023041511)及之后版本、V3.2.4 BP3(oceanbase-3.2.4.3-103000032023041816)及之后版本、V4.1.0 BP1(oceanbase-4.1.0.0-101000052023050621)及之后版本。
解决方法二:
将 IN 表达式改成等价的 OR 表达式,例如
c1 in ('1','2') => (c1 = '1' or c1 = '2')。通过 Hint 禁止走包含 IN 表达式所在列的索引,例如
select /+full(t1)/...。在 IN 表达式后面加个
is true(适用于命中主键索引的场景),例如c1 in ('1','2') is true。如果出现问题的 OceanBase 数据库版本为以下版本或更高,可以通过隐藏配置项
_enable_in_range_optimization关闭 IN 优化。OceanBase 数据库企业版 V3.2.3 BP8 Hotfix5(oceanbase-3.2.3.3-108050012023070409)及之后版本。
OceanBase 数据库企业版 V3.2.4 BP4(oceanbase-3.2.4.4-104000052023062021)及之后版本。
OceanBase 数据库企业版 V4.1.0 BP2(oceanbase-4.1.0.1-102000042023061309)及之后版本。
规避方式
无。
相关文档
关于 IN 优化引入的其他正确性问题,参见:IN 优化引入的正确性问题一、IN 优化引入的正确性问题二、IN 优化引入的正确性问题三。