Oracle 索引创建语法

Oracle Index creation syntax

我在使用带有聚合函数的 SQL 查询时遇到了一些性能问题,所以我认为了解索引创建的确切工作原理是个好主意。我遇到了一件我无法理解的事情:这两个创建指令之间有什么区别?:

1.)CREATE INDEX FIELD1_INDEX ON TABLE1 (FIELD1) ONLINE TABLESPACE XXX;
   CREATE INDEX timeofrequest_INDEX ON TABLE1 (timeofrequest) ONLINE TABLESPACE XXX;

2.)CREATE INDEX COMBINED_INDEX ON TABLE1 (FIELD1, FIELD2) ONLINE TABLESPACE XXX;

我问的原因是我有这样的查询:

SELECT SUM(field1) FROM table1 WHERE timeofrequest BETWEEN 1 AND 2;

表 1 包含大量数据,因此此查询需要 20 多秒才能准备好。为避免运行时间过长,我尝试采用方法 1,并为每个受影响的字段创建一个索引。确实,还是太慢了。通过分析执行计划,我看到使用了 timeofrequest 索引,但没有使用 field1 索引。如果我用一条语句创建一个组合语句会有帮助吗?这有什么区别吗?

所以您的前两个索引与您的第三个索引不同,因为前两个索引仅使用单个列作为索引。您的第三个索引由两个不同的索引列组成,但即使您仅提供索引中列出的第一列,第三个索引仍然可以使用……这被称为复合索引。 Oracle 实际上只能在单个查询语句中使用 SINGLE 索引,CBO 会找出最佳使用选项。

在您的第一个示例中,您有两个针对各个列的索引。您的第二个示例是具有两列的 SINGLE 索引。对于任何给定的单个 select 语句,您的第一个示例将只使用一个,但不会同时使用两个(CBO 将根据您的查询决定使用什么...)。

示例:

SELECT SUM(field1) FROM table1 WHERE timeofrequest BETWEEN 1 AND 2;

这只会尝试使用您针对 timeofrequest 放置的索引。事实上,它会尝试进行范围扫描。

第二个索引示例:

SELECT SUM(field1) FROM table1 WHERE FIELD1 = 'x';

假设您没有仅针对 'FIELD1' 的索引,这将利用您现有的 COMBINED_INDEX,并根据索引的第一个字段获取所有记录。

如果你有:

SELECT SUM(field1) FROM table1 WHERE FIELD2 = 'y';

这不会使用 combined_index,因为索引是围绕首先使用 FIELD1,然后是 FIELD2 构建的。

如果你有:

SELECT SUM(field1) FROM table1 WHERE FIELD1 = 'x' and FIELD2 = 'y';

这仍将使用 COMBINED_INDEX,但您在这里提供了更精细的粒度级别。它将利用完整索引(field1 和 field2...)更快地 return 您的行。为什么这有用?好吧,您可能在 FIELD1 上有一个索引,并且仅在 field1 上搜索仍然会产生数千(或数万,或数百万......)记录,因此能够提供另一列作为索引的一部分将简单地帮助定位您需要的记录...反过来提供更高的 selectivity.

重要提示!请记住,CBO 会找出最佳方法。如果您对该列的 table 的基数很差(研究 table 基数...),您甚至可能根本不使用索引,并进行完整的 table 扫描根据 CBO 的说法会更好。如果您的基数很高,但仍未使用索引,则可能需要分析 table 及其上的索引,然后重新运行解释计划以查看是否获得新结果。也有可能由于 table 中的大量数据发生变化而最近没有对其进行分析,因此基数可能较低。分析你的 table/indices 是一件非常重要的事情,但很容易被忽视。在多个场合,我发现我工作的实例只是重新分析 table and/or 索引取得了令人难以置信的改进。

请查看 table 的分析和 DBMS_STATS 的使用。

https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_stats.htm

另一个解决方案是,如果您有大量数据,而您的 "time of request" 列实际上只有一小部分不同的值(也许在您的 table 的 5000 万条记录中只有20 个不同的值..),那么您可能会选择设置分区 table 并从那里提供索引。它将大大提高查询性能时间。