我们有一个简单的join语句,其中一些when子句可能变成null。该语句由应用程序生成。当我们有 this is null约束时,查询计划就会出现问题。
我们遵循 StackExchange 上的文章中描述的方法,并为列创建了一个复合索引 - 可为空的和我们加入的那个。只有当我们只选择索引列时才有帮助。如果我们选择未索引的列,它将被忽略,而查询结果是相同的 - 例如,没有选择行。
我们看到的唯一选择 - 更改应用程序的逻辑,但可能还有办法在数据库级别解决这个问题?
--Illustrative sample. Prepare tables and indexes:
create table tableA
(
Acol1 varchar2(32) NOT NULL,
Acol2 varchar2(32),
Acol3 varchar2(32)
);
insert into tableA (Acol1, Acol2, Acol3)
values ('abcd1','abcd2A','abcd3A');
create table tableB
(
Bcol1 varchar2(32) NOT NULL,
Bcol2 varchar2 (32),
Bcol3 varchar2 (32)
);
insert into tableB (Bcol1, Bcol2, Bcol3)
values ('abcd1','abcd2B','abcd3B');
create index tableA_col12 on tableA (acol1, acol2);
create index tableB_col1 on tableB (Bcol1);
commit;
然后我们检查计划:
1.
select a.Acol1 from tableA a join tableB b on a.Acol1 = b.Bcol1 where Acol2 is null;
--no rows selected
计划 1 - 范围扫描
2.
select * from tableA a join tableB b on a.Acol1 = b.Bcol1 where Acol2 is null;
--no rows selected
Plan2(上面的相同链接) - 全表扫描
提高性能的最佳方法是什么:更改查询、使用更智能的索引或应用固定计划?
*更新*当我准备这个问题时,我的样本计划自行更改,现在我们有Plan2*而不是 Plan2 - 没有全表扫描。但是,如果我重新创建示例(删除表并再次准备它们) - 计划再次是 Plan2(全表扫描)。这个技巧在实际数据库中不会发生。