我正在运行以下查询。
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()
函数而感到困惑。
请同样分享您的解释。
答案 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)
正如您所提到的,汇总函数的存在会导致索引被忽略。
基于函数的索引包括由函数转换的列,例如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
的成本低于使用索引,那么它将忽略索引。这么说,我现在告诉你索引的可能问题 -
(Field_4,Field_1,Field_2,Field_3)
,那么它会更快,因为您在Field_4上具有相同性 - Table_1.Field_4 = '31-oct-2011'
。想想这是 - Table_1.Field_4 = '31-oct-2011'
会为您提供较少的选项来选择Table_1.Field_3 NOT IN (1, 3)
的最终结果。自从你加入以来,事情可能会发生变化。总是最好看一下执行计划并相应地设计你的索引/ sql。