按字段创建分组索引?

one*_*jig 29 sql oracle indexing plsql

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

例如:

select * 
from some_table
where field_one is not null and field_two = ?
group by field_three, field_four, field_five
Run Code Online (Sandbox Code Playgroud)

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

Eri*_*lje 16

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

  • @Eric:在我看来,GROUP BY 订单对 Oracle 很重要。更改 GROUP BY 中列的顺序不会更改查询的语义,因此不应更改计划。证明? (2认同)

Qua*_*noi 9

不,这可能是不正确的.

如果你有一个大表,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
        )
Run Code Online (Sandbox Code Playgroud)

计划是:

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
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,有没有TABLE SCANt_left这里.

相反,Oracle接受索引,id并将value它们连接起来rowid(id, value)从连接结果中获取对.

现在,您的查询:

SELECT  *
FROM    some_table
WHERE   field_one is not null and field_two = ?
GROUP BY
        field_three, field_four, field_five
Run Code Online (Sandbox Code Playgroud)

首先,它不会编译,因为您*从带有GROUP BY子句的表中进行选择.

您需要*根据非分组列的分组列和聚合替换表达式.

您很可能会从以下索引中受益:

CREATE INDEX ix_sometable_23451 ON some_table (field_two, field_three, field_four, field_five, field_one)
Run Code Online (Sandbox Code Playgroud)

因为它将包含用于过滤field_two,排序field_three, field_four, field_five(有用GROUP BY)和确保它的所有field_one内容NOT NULL.