or条件查询比较慢,前后2个条件,只用到了其中一个索引

【 使用环境 】生产环境
【 OB or 其他组件 】oceanbase
【 使用版本 】4.2.1-BP8
【问题描述】
执行如下sql:
select id,plat_code from plat_order_main
where ID = ‘qwdddd’ or logis_tracking_no = ‘qwdqwddw’

explain计划显示,只用了id主键索引。logis_tracking_no 这个字段也有索引的。没有用上

mysql5.6应该是已经优化了or条件查询的如下。会解析分别使用2个索引查询

以下是ob执行的sql。使用obdiag收集的执行计划信息
obdiag_gather_pack_20240823102448.zip (142.1 KB)

是否可以union all改写一下

这个优化懂的。
只是历史存量sql不知道有多少。
这里是个探讨贴

执行一下 这个执行计划整个复制放到txt文本里 发一下
explain extended select id,plat_code from plat_order_main
where ID = ‘qwdddd’ or logis_tracking_no = ‘qwdqwddw’

可以用obdiag 收集这表信息 根据trace_id收集 刚才看信息 收集不详细
obdiag gather scene run --scene=observer.perf_sql --env “{db_connect=’-hxx -Pxx -uxx -pxx -Dxx’, trace_id=‘xx’}”

升级一下obdiag 到2.3.0,收集到的报告数据会更丰富一点

找到问题了。
select * from talbe_aaa
where prod_s_id = 111 or s_sku = ‘xxxx’
;
select * from talbe_aaa
where prod_s_id = ‘111’ or s_sku = ‘xxx’

or查询的时候,对应类型转换不怎么友好。
如上。 prod_s_id是个int类型字段。
当传入的为字符串时。 无法自动转换类型。就无法使用索引。

而union语句则不影响数字类型的自动转换

select * from talbe_aaa
where prod_s_id = ‘111’

union

select * from talbe_aaa
where
s_sku = ‘xxx’;

期待后面的版本,能对or查询的字段类型转换做出优化吧

2 个赞

继or查询之后,发现了另一个 没有进行类型自动转换而导致索引失效的场景

表结构
CREATE TABLE testaa (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
product_id varchar(25) NOT NULL DEFAULT ‘’,
store_acct_id int(10) NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id),
KEY idx_product_id_store_acct_id (product_id, store_acct_id)
) AUTO_INCREMENT = 1 ;

查询语句:
SELECT
psps.id
FROM
testaa psps
WHERE
psps.product_id IN (
172970403530
);

由于 product_id 为varchar类型。
in 查询中传参为 数字。未自动转换类型,导致索引失效,走了全表扫描

传参改为字符串时,索引才生效

mysql中会自动转换类型,使用索引。实验如下

希望ob能在类型自动转换方面做出更好的优化吧。

1 个赞

你好 首先感谢你的反馈 问了相关的同学 这个是符合ob的预期的,目前大多数有cast场景走不上索引的,有少一部分内核可能绕过去了,mysql也不是隐式转换和or的场景一定会走索引的,在有些情况下,是走的索引的,尽量按照标准的书写方式,这样才能保证不发生隐式转换,符合走索引的预期。

1 个赞

增量代码肯定会要求按照标准的方式写。
主要是历史代码问题。
也不多。只能后面应改尽改吧

好的 你在修改一下 如果碰到执行不优语句 你也可以发到社区 大家可以一起交流探讨 给你一些建议