【问题标题】:Oracle Index creation syntaxOracle 索引创建语法
【发布时间】:2016-06-29 15:17:36
【问题描述】:

我在使用带有聚合函数的 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;

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

【问题讨论】:

    标签: oracle performance indexing syntax creation


    【解决方案1】:

    因此,您的前两个索引与第三个索引不同,因为前两个索引仅使用单列作为索引。您的第三个索引由索引的两个不同列组成,但即使您只提供索引中列出的第一列,第三个索引仍然可以使用……这称为复合索引。 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”的 INDEX,这将利用您现有的 COMBINED_INDEX,并根据索引的第一个字段获取所有记录。

    如果你有:

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

    这不会使用组合索引,因为索引是先使用 FIELD1,然后是 FIELD2。

    如果你有:

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

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

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

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

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

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

    【讨论】:

    • 非常感谢,感谢您的帮助
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多