在三列组合索引中搜索两列 - Oracle

时间:2009-08-20 22:37:51

标签: sql oracle

我的一个表中有三列的复合索引。它可以找到我的查询在哪里有三列。当我的搜索查询只有三分之二时,事情似乎不再那么快了!

你知道如何解决这个问题吗?

谢谢,

P.S。 表

APPL_PERF_STATS

在(current_appl_id,event_name& generic_method_name)上有复合索引 这个花了2分钟(使用复合索引中的所有列):

  

SELECT * FROM APPL_PERF_STATS WHERE(GENERIC_METHOD_NAME!='NULL'AND   CURRENT_APPL_ID!='NULL'和EVENT_NAME!='NULL')和ROWNUM< 502   AND current_appl_id ='OMS'AND event_name ='OMS-CeaseProduct'AND   generic_method_name ='CE CallForwardFixedCOProduct'AND   appl_perf_interval_typ_id = 1440 AND cover_period_start_ts> =   to_date('20 -07-2008 14:36','dd-mm-yyyy HH24:mi')和   cover_period_start_ts< = to_date('19 -08-2009 14:36','dd-mm-yyyy   HH24:mi')按CURRENT_APPL_ID,EVENT_NAME,GENERIC_METHOD_NAME订购,   CREATE_TS

这个需要12分钟才能运行(在复合索引中只使用三分之二):

  

SELECT * FROM APPL_PERF_STATS WHERE(GENERIC_METHOD_NAME!='NULL'AND   CURRENT_APPL_ID!='NULL'和EVENT_NAME!='NULL')和ROWNUM< 502   AND current_appl_id ='OMS'AND event_name ='OMS-CeaseProduct'AND   appl_perf_interval_typ_id = 1440 AND cover_period_start_ts> =   to_date('20 -07-2008 14:36','dd-mm-yyyy HH24:mi')和   cover_period_start_ts< = to_date('19 -08-2009 14:36','dd-mm-yyyy   HH24:mi')按CURRENT_APPL_ID,EVENT_NAME,GENERIC_METHOD_NAME订购,   CREATE_TS

2 个答案:

答案 0 :(得分:4)

  • 你知道你要搜索的三个术语中的哪两个?为了获得最大效率,Oracle将仅使用您在索引的前导列上查询的索引。也就是说,(column_1column_2column_3)上的索引可以像column_1column_2上的查询一样有效地用于查询反对所有三个。如果您在column_2column_3上搜索,则(至少)效率会大幅下降,因为这些不是主要列。
  • 您使用的是哪个版本的Oracle?根据Oracle版本和前导列的选择性,如果您的查询不包含索引的前导列,Oracle可能能够使用所谓的“索引跳过扫描”来利用索引。这将比常规索引范围扫描效率低,但它可能比表扫描更有效。
  • 查询的查询计划是什么,并不像您希望的那么快?我们可以猜测优化器可能会做什么,但看到实际的查询计划会更有用。

答案 1 :(得分:3)

“当我的搜索查询只有三分之二时,事情似乎不再那么快了!” 你还期待别的吗?

如果你不得不打电话簿中的所有“史密斯,约翰”,你可能有50个参赛作品需要5个小时。如果您拨打电话簿中的所有“史密斯”条目,则可能有500个条目,并且需要十倍的时间。

真正的问题是,对于您期望处理的数据量,性能是合理/可接受的。

查看查询,一个选项可能是考虑单独或与其他列组合索引cover_period_start_ts和/或appl_perf_interval_typ_id。我怀疑在找到符合索引条件的行时会浪费很多时间,转到表然后拒绝该行,因为时间戳或间隔类型不符合指定的条件。

PS。如果查看查询,您将看到所有三列都在where子句的!='NULL'部分中指定,因此从技术上讲,它使用索引的所有三列,但是两个作为access_predicate,一个作为filter_predicate