按字段创建分组索引?

时间:2009-09-18 14:55:00

标签: sql oracle plsql indexing

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

例如:

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

我正在测试我为上面创建的索引,此查询的唯一相关索引是为field_two创建的索引。在任何其他字段上创建的其他单字段或复合索引将不会用于上述查询。这听起来不错吗?

3 个答案:

答案 0 :(得分:13)

这可能是正确的,但这取决于您拥有多少数据。通常我会为GROUP BY中使用的列创建索引,但在您的情况下,优化器可能已经决定在使用field_two索引后,返回的数据不足以证明使用GROUP的其他索引是合理的BY

答案 1 :(得分:8)

不,这可能不正确。

如果你有一个大表,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

如您所见,此处TABLE SCAN上没有t_left

相反,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

答案 2 :(得分:2)

  

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

没有。在某种意义上,无论是否存在任何索引,都不需要运行查询。提供索引是为了提高查询性能。

然而,它可以提供帮助;但我不想添加索引只是为了帮助一个查询,而不考虑新索引对数据库可能产生的影响。

  

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

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

然而,您是否真的需要担心GROUP BY表现,这是一个值得思考的重要问题。