2009-09-18 55 views
21

您是否需要按照Oracle数据库中的字段为组的字段创建索引?为分组字段创建索引?

例如:

select * 
from some_table 
where field_one is not null and field_two = ? 
group by field_three, field_four, field_five 

我测试我的上述和该查询的唯一相关的索引创建的索引为field_two创建的索引。其他任何字段上创建的其他单字段或复合索引都不会用于上述查询。这听起来正确吗?

回答

11

这可能是正确的,但这取决于你有多少数据。通常,我会为我在GROUP BY中使用的列创建索引,但在您的情况下,优化程序可能已决定在使用field_two索引后没有足够的数据返回来证明使用GROUP的其他索引通过。

+1

+1提到优化器,这可能是最可能的原因。 – 2009-09-18 14:59:14

+0

谢谢你的回应。我没有意识到解释计划取决于表中的数据量。表中目前没有数据,这就解释了优化器可能跳过其他索引的原因。 在另一个说明中,只有field_three和field_four没有field_five的复合索引仍然会用在像上面那样的查询中吗?这不包括group by子句中的所有字段。 – onejigtwojig 2009-09-18 15:04:01

+0

@Mark - 解释它。请参阅我的编辑,以获取有关Oracle可以使用哪些索引的更多信息。 – 2009-09-18 15:08:29

7

不,这可能是不正确的。

如果您有一个大表,Oracle可能更喜欢从索引而不是表中导出字段,即使没有涵盖所有值的单个索引。

在我的博客最新文章:

,存在一种Oracle不使用全表扫描,而是将两个指标来获取列值的查询:

SELECT l.id, l.value 
FROM t_left l 
WHERE NOT EXISTS 
     (
     SELECT value 
     FROM t_right r 
     WHERE r.value = l.value 
     ) 

的计划是:

SELECT STATEMENT 
HASH JOIN ANTI 
    VIEW , 20090917_anti.index$_join$_001 
    HASH JOIN 
    INDEX FAST FULL SCAN, 20090917_anti.PK_LEFT_ID 
    INDEX FAST FULL SCAN, 20090917_anti.IX_LEFT_VALUE 
    INDEX FAST FULL SCAN, 20090917_anti.IX_RIGHT_VALUE 

正如您所见,t_left这里没有TABLE SCAN

相反,Oracle呈现idvalue指标,加入他们的rowid并得到从加入结果(id, value)双。

现在,您的查询:

SELECT * 
FROM some_table 
WHERE field_one is not null and field_two = ? 
GROUP BY 
     field_three, field_four, field_five 

首先,它不会编译,因为你是从表一中GROUP BY条款选择*

您需要用基于非分组列的分组列和聚合的表达式替换*

您将最有可能从以下索引中获益:

CREATE INDEX ix_sometable_23451 ON some_table (field_two, field_three, field_four, field_five, field_one) 

,因为它将包含在field_two一切两个过滤,排序上field_three, field_four, field_five(为GROUP BY有用),并确保field_oneNOT NULL

+1

非常有趣 - 我不认为我以前见过(Oracle会加入两个索引并完全避免表) – 2009-09-18 15:09:51

+0

'@Eric Petroelje':有一个特殊的提示'INDEX_JOIN',强制这个方法。 – Quassnoi 2009-09-18 15:19:23

2

您是否需要在Oracle数据库中按字段创建组字段的索引?

不需要,无论是否存在任何索引,查询都会运行。提供索引来提高查询性能。

但是,它可以帮助;但我不愿意添加索引来帮助查询,而不考虑新索引对数据库的可能影响。

...此查询的唯一相关索引是为field_two创建的索引。其他任何字段上创建的其他单字段或复合索引都不会用于上述查询。这听起来正确吗?

并不总是如此。通常GROUP BY将要求Oracle执行排序(但不总是);您可以通过在要排序的列上提供合适的索引来消除排序操作。

但是,您是否真的需要担心GROUP BY的性能,这是您需要考虑的一个重要问题。

+0

upvote for“可以消除排序操作..”。顺便说一句,这篇文章有更多的细节http://use-the-index-luke.com/sql/sorting-grouping/indexed-group-by – waltersu 2017-06-20 13:22:54