选择未编制索引的列(Oracle)时,将忽略复合索引



我们有一个简单的join语句,其中一些when子句可能会变成,但它为null。该语句由应用程序生成。当我们有is-null约束时,查询计划就会出现问题
我们遵循了StackExchange文章中描述的方法,为列创建了一个复合索引-可为null的列和我们连接的列。只有当我们只选择索引列时,这才有帮助。如果我们选择未索引的列,它将被忽略,而查询结果是相同的——例如,没有选择行

我们看到的唯一选项是更改应用程序的逻辑,但可能还有办法在数据库级别解决这个问题?

--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

Plan1-距离扫描

2.

 select * from tableA a join tableB b on a.Acol1 = b.Bcol1 where Acol2 is null;
--no rows selected

Plan2(与上面的链接相同)-全表扫描

提高性能的最佳方法是什么:更改查询、使用更智能的索引或应用固定计划?

*更新*当我准备这个问题时,我的样本计划自行更改,现在我们有Plan2*而不是Plan2-没有全表扫描。然而,如果我重新创建样本(放下表格并再次准备),则计划再次为Plan2(完整表格扫描)。这个技巧在实际的数据库中不会发生。

我的评论有点轻率,所以我会给你更多的细节。以下是一些在优化SQL系统和特定查询方面做得更好的一般提示

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

  • 第二,在你有了一个合适大小的表(根据你的内存,至少有5万行)之后,你需要确保你在表上运行统计数据,或者优化器(和索引)不能正常工作

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

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

在这种情况下,对于更大的表,我认为(需要注意的是,关于数据库和数据模型,还有很多事情我不知道)只需在索引中添加更多列就可以了——但请使用Oracle工具,看看它有什么建议。先试试。

相关内容

  • 没有找到相关文章

最新更新