为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】:
DM Database Server 64 V8
DB Version: 0x7000c
03134284194-20240703-234060-20108
Msg Version: 12
Gsu level(5) cnt: 0
【操作系统】:
Kylin Linux Advanced Server
【CPU】:
麒麟920
【问题描述】*:
两个 sql 语句:
SELECT * FROM page WHERE ((deletedat > '2024-08-22 20:38:36' OR deletedat IS NULL)) order by id desc limit 1;
SELECT * FROM page WHERE ((deletedat > '2024-08-22 20:38:36' OR deletedat IS NULL) AND ( deletedat IS NULL)) order by id desc limit 1;
我数据库里只有一条数据, deletedat 为 null, 第一个查询能查出数据,第二个查询则不能,但是两个 sql 应该是 等价的,为什么会这样呢?
貌似这个是 OPTIMIZER_OR_NBEXP 参数的问题,我做了个实验,当这个参数为16时,就查询不到记录,你看看 V$DM_INI 中这个参数值是不是29,如果是的话,修改成13,或其他参数值试试看
测试过程
--查询 OPTIMIZER_OR_NBEXP 参数设置值,我这数据库版本为20240812,参数默认值为 29,即 1 + 4 + 8 + 16
select * from v$dm_ini where para_name = 'OPTIMIZER_OR_NBEXP';
--通过HINT方式传递其他参数值,能够正常查询出结果
SELECT /*+ OPTIMIZER_OR_NBEXP(13)*/*
FROM page2
WHERE (deletedat > '2024-08-22 20:38:36' OR deletedat IS NULL)
AND deletedat IS NULL;
--修改hint中参数值为16后,再查下就无结果,所以我觉得可能与这个参数值的处理逻辑有关
SELECT /*+ OPTIMIZER_OR_NBEXP(16)*/*
FROM page2
WHERE (deletedat > '2024-08-22 20:38:36' OR deletedat IS NULL)
AND deletedat IS NULL;
--用下面SQL能查到这个参数的说明信息
select * from v$dm_ini_desc where para_name = 'OPTIMIZER_OR_NBEXP';
/*
OR表达式的优化方式。
0:不优化;
1:生成UNION_FOR_OR操作符时,优化为无KEY比较方式;
2:OR表达式优先考虑整体处理方式;
4:相关子查询的OR表达也优考虑整体处理方式;
8:OR布尔表达式的范围合并优化;
16:同一列上同时存在常量范围过滤和IS NULL过滤时的优化,如c1 > 5 or c1 is null。
支持使用上述有效值的组合值,如7表示同时进行1、2、4的优化
*/
我验证你这个sql,2个查询都是可以查询得到结果的。
你检查一下你的COMPATIBLE_MODE参数值是多少,如果修改过,可以恢复为0试试。