索引是否与oracle中的组函数一起使用?

时间:2011-10-17 06:54:11

标签: sql oracle oracle11g indexing

我正在运行以下查询。

SELECT Table_1.Field_1,
           Table_1.Field_2,
           SUM(Table_1.Field_5) BALANCE_AMOUNT
      FROM Table_1, Table_2
     WHERE Table_1.Field_3 NOT IN (1, 3)
       AND Table_2.Field_2 <> 2
       AND Table_2.Field_3 = 'Y'
       AND Table_1.Field_1 = Table_2.Field_1
       AND Table_1.Field_4 = '31-oct-2011'
     GROUP BY Table_1.Field_1, Table_1.Field_2;

我为(Field_1,Field_2,Field_3,Field_4)的列Table_1创建了索引,但索引未被使用。

如果我从select子句中删除SUM(Table_1.Field_5),则会使用索引。

如果优化器没有使用此索引或因为我在查询中使用的SUM()函数而感到困惑。

请同样分享您的解释。

4 个答案:

答案 0 :(得分:5)

删除SUM后,您还会从查询中删除field_5。然后可以在索引中找到回答查询所需的所有数据,这可能比扫描表更快。如果您将field_5添加到索引,则SUM 的查询可能使用索引。

答案 1 :(得分:3)

如果您的查询返回表的大部分行,Oracle可能会认为执行全表扫描比索引和表堆之间的“跳跃”更便宜(以获取Table_1.Field_5中的值)。

尝试将Table_1.Field_5添加到索引中(从而用索引覆盖整个查询)并查看是否有帮助。

请参阅使用The Index Luke的Index-Only Scan: Avoiding Table Access,了解正在发生的事情的概念性说明。

答案 2 :(得分:1)

正如您所提到的,汇总函数的存在会导致索引被忽略。

function based indexes

  

基于函数的索引包括由函数转换的列,例如UPPER函数,或包含在表达式中的列,例如col1 + col2。

     

在转换的列或表达式上定义基于函数的索引允许在WHERE子句或ORDER BY子句中使用该函数或表达式时使用索引返回数据。因此,当频繁执行的SQL语句在WHERE或ORDER BY子句中包含转换列或表达式中的列时,基于函数的索引可能是有益的。

然而,与所有基于函数的索引have their restrictions:

一样
  

基于函数的索引中的表达式不能包含任何聚合函数。表达式必须仅引用表格中一行中的列。

答案 3 :(得分:0)

虽然我在这里看到了一些好的答案,但是错过了几个重点 -

SELECT Table_1.Field_1,
           Table_1.Field_2,
           SUM(Table_1.Field_5) BALANCE_AMOUNT
      FROM Table_1, Table_2
     WHERE Table_1.Field_3 NOT IN (1, 3)
       AND Table_2.Field_2 <> 2
       AND Table_2.Field_3 = 'Y'
       AND Table_1.Field_1 = Table_2.Field_1
       AND Table_1.Field_4 = '31-oct-2011'
     GROUP BY Table_1.Field_1, Table_1.Field_2;

说在select子句中使用SUM(Table_1.Field_5)会导致索引不能正确使用。您仍可以使用(Field_1,Field_2,Field_3,Field_4)上的索引。但是你的索引和SQL查询存在问题。

由于您的索引仅在(Field_1,Field_2,Field_3,Field_4)上,即使您的索引被使用,DB也必须访问实际的表行以获取Field_5以应用过滤器。现在它完全依赖于sql优化器制定的执行计划,哪一个具有成本效益。如果SQL优化器发现full table scan的成本低于使用索引,那么它将忽略索引。这么说,我现在告诉你索引的可能问题 -

  1. 正如其他人所说,你可以简单地将Field_5添加到索引中,这样就不需要单独的表访问了。
  2. 您的索引顺序非常重要。例如。在您的情况下,如果您将订单作为(Field_4,Field_1,Field_2,Field_3),那么它会更快,因为您在Field_4上具有相同性 - Table_1.Field_4 = '31-oct-2011'。想想这是 -
  3. Table_1.Field_4 = '31-oct-2011'会为您提供较少的选项来选择Table_1.Field_3 NOT IN (1, 3)的最终结果。自从你加入以来,事情可能会发生变化。总是最好看一下执行计划并相应地设计你的索引/ sql。