使用索引进行 Oracle Sql 调优

Posted

技术标签:

【中文标题】使用索引进行 Oracle Sql 调优【英文标题】:Oracle Sql tuning with index 【发布时间】:2017-02-10 17:39:37 【问题描述】:

我有一个表 T 有大约 500000 条记录。该表是一个分层表。 我的目标是根据父子关系的某些条件通过自我加入同一个表来更新表 更新查询需要很长时间,因为行数非常高。我在列上创建了一个唯一索引,有助于识别要更新的行(平均 x 和 Y)。创建索引后,成本降低了,但查询的执行速度仍然慢了很多。

这是我的查询格式

update T
set a1, b1
= (select T.parent.a1, T.parent.b1
 from T T.paremt, T T.child
where T.parent.id = T.child.Parent_id
and T.X = T.child.X
and T.Y = T.child.Y

在创建索引后,执行计划显示它正在对 CRS.PARENT 进行索引扫描,但正在对 CRS.CHILD 进行全表扫描,并且在更新期间,查询将永远完成。

请提出解决此问题的任何提示或建议

【问题讨论】:

请运行EXPLAIN PLAN FOR update T ....(resto uf your query)....,然后运行SELECT * FROM table( DBMS_XPLAN.Display ),然后复制最后一个查询的结果(作为文本!!!- 不是位图!!!)并将其附加到问题中。有关解释计划命令的更多信息,您可以在此处找到:docs.oracle.com/cd/B28359_01/server.111/b28274/… 【参考方案1】:

您正在更新所有 500,000 行,因此索引不是一个好主意。 500,000 次索引查找将花费比它需要的时间更长的时间。

使用MERGE 语句会更好地为您服务。

很难准确地说出你的表结构是什么,但它看起来像这样,假设 X 和 Y 是 T 中的主键列(...可能是错误的):

MERGE INTO T
USING ( SELECT  TC.X,
                TC.Y,
                TP.A1,
                TP.A2 
        FROM    T TC 
        INNER JOIN T TP ON TP.ID = TC.PARENT_ID ) U
ON ( T.X = U.X AND T.Y = U.Y )
WHEN MATCHED THEN UPDATE SET T.A1 = U.A1, 
                             T.A2 = U.A2;

【讨论】:

如果您要更新所有 500,000,最好重新创建表并执行 INSERT... AS SELECT... @BobC 您可能是对的,但是更新 500k 行表中的两列应该不会花费太长时间。我不认为我会将 DDL 的复杂性引入这个过程,除非我真的需要最大化性能。 发布的问题是关于性能的,这是我的专业领域。您是对的,执行更新可能“足够好”,但我想至少表明可以实现出色的性能。 DDL/DML 不会那么复杂。然而,它开启了直接路径加载(通过 APPEND 提示)和并行性的可能性。使用直接路径加载进行转换与修改也将消除大部分撤消和重做的开销。再说一次,我只是想让这篇文章的读者明白什么是可能的。 @BobC 够公平的。但需要明确的是,它还引入了至少一个短窗口,在此期间数据将不可用。除非您打算删除而不是截断,在这种情况下,您将失去大部分(如果不是全部)性能优势。 @Matthew McPeak,感谢您理解问题并提供最佳解决方案。

以上是关于使用索引进行 Oracle Sql 调优的主要内容,如果未能解决你的问题,请参考以下文章

性能调优调优的常见思路和方法

性能调优调优的常见思路和方法

JVM调优调优方法

Oracle SQL调优

01JVM调优调优--总结

Oracle / SQL 调优顾问