1

我们有一个简单的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(全表扫描)。这个技巧在实际数据库中不会发生。

4

1 回答 1

0

我的评论有点轻率,所以我会尝试为您提供更多细节。以下是一些有助于更好地优化 SQL 系统和特定查询的一般技巧

  • 首先@GordonLinoff 是对的(一如既往)你不会从一张小桌子上得到任何有意义的东西。优化器知道并且会以不同的方式工作。

  • 其次,在您拥有一个大小合适的表(至少 50k 行,具体取决于您的内存)之后,您需要确保在您的表上运行统计信息,否则优化器(和索引)将无法正常工作

  • 第三,你需要使用工具,学习如何理解执行计划——如果不深入理解系统告诉你的内容,你就无法更好地掌握这些技术。现代 sql 数据库具有查看查询和建议索引的工具——使用它们,就像您可以学到很多东西的执行计划一样。请记住,这些工具并非万无一失,您需要尝试这些建议并查看它们是否有效。

  • 最后,多读书。我认为特别有趣的一个来源是 stackoverflow 用户Quassnoi ,他在explainextended上有一个博客。虽然最近这个博客(以及他的许多答案)没有那么活跃,但很有启发性,我希望你会喜欢它们。有很多关于这个主题的博客和书籍,每一点都有帮助。

在这种情况下,对于您更大的表,我认为(这有一个警告,我不知道您的数据库和数据模型有很多事情)只需向索引添加更多列即可 - 但使用 Oracle 工具和看看它的建议。先试试那个。

于 2015-11-10T00:24:27.380 回答