问题现象
某些情况下,OceanBase 数据库在进行多分区扫描时,即使有索引并且使用索引非常快,也会抛弃索引而使用全表扫描,OceanBase 数据库的优化器评估的全表扫描的 cost 会远远低于索引扫描呢?
以下面示例进行说明。
假设有一张名为 t 的分区表,根据 a 列按天进行 24 个 range 分区。存在一个联合索引 idx1:(b,a),其中 b 的选择性较好。
OceanBase 数据库在执行如下语句时,会抛弃索引 idx1,而使用全表扫描,从而导致执行效率地下。
select * from t where b='xxx' and a>='2022-02-27' and a<='2022-02-28'
问题原因
过滤 a>='2022-02-27' and a<='2022-02-28' 裁剪出了两个分区,P22、P23,其中 P23 是大分区,数据量比较多,但是满足b='xxx' 条件的数据量比较少,P22 分区满足 b='xxx' 的数据量比较多。 优化器对于分区表的行数估计策略是:选择最大的分区估算,然后乘以分区数,所以这里优化器会选择 P23 分区估行,然后乘以二,估算的行数偏小。
在行数比较少的情况下,优化器选择了主表扫描,而没有选择索引扫描。
解决方法
这种问题一般是 SQL 的写法有问题,可以尝试通过以下方法解决。
- 优化 SQL 写法:除了查 27 号的数据,还要查一点 28 号的数据,这种查询是不合理的,建议尝试优化 SQL 写法。
- 使用 Hint:可以在 SQL 语句中使用 Hint 来指导优化器选择索引扫描。
- 绑定 Outlint。
适用版本
OceanBase 数据库 V2.2.77 版本。