Álv*_*lez 2 oracle performance oracle9i
在客户端的9i服务器上部署在10g XE上开发的应用程序时,我遇到了性能问题.相同的查询根据服务器生成完全不同的查询计划:
SELECT DISTINCT FOO.FOO_ID AS C0,
GEE.GEE_CODE AS C1,
TO_CHAR(FOO.SOME_DATE, 'DD/MM/YYYY') AS C2,
TMP_FOO.SORT_ORDER AS SORT_ORDER_
FROM TMP_FOO
INNER JOIN FOO ON TMP_FOO.FOO_ID=FOO.FOO_ID
LEFT JOIN BAR ON FOO.FOO_ID=BAR.FOO_ID
LEFT JOIN GEE ON FOO.GEE_ID=GEE.GEE_ID
ORDER BY SORT_ORDER_;
Run Code Online (Sandbox Code Playgroud)
Oracle数据库10g快捷版10.2.0.1.0版 - 生产:
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 67 | 10 (30)| 00:00:01 |
| 1 | SORT UNIQUE | | 1 | 67 | 9 (23)| 00:00:01 |
| 2 | NESTED LOOPS OUTER | | 1 | 67 | 8 (13)| 00:00:01 |
|* 3 | HASH JOIN OUTER | | 1 | 48 | 7 (15)| 00:00:01 |
| 4 | NESTED LOOPS | | 1 | 44 | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | TMP_FOO | 1 | 26 | 2 (0)| 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID| FOO | 1 | 18 | 1 (0)| 00:00:01 |
|* 7 | INDEX UNIQUE SCAN | FOO_PK | 1 | | 0 (0)| 00:00:01 |
| 8 | TABLE ACCESS FULL | BAR | 1 | 4 | 3 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID | GEE | 1 | 19 | 1 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | GEE_PK | 1 | | 0 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
Oracle9i版本9.2.0.1.0 - 64位生产:
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 98M| 6546M| | 3382K|
| 1 | SORT UNIQUE | | 98M| 6546M| 14G| 1692K|
|* 2 | HASH JOIN OUTER | | 98M| 6546M| 137M| 2874 |
| 3 | VIEW | | 2401K| 109M| | 677 |
|* 4 | HASH JOIN OUTER | | 2401K| 169M| 40M| 677 |
| 5 | VIEW | | 587K| 34M| | 24 |
|* 6 | HASH JOIN | | 587K| 34M| | 24 |
| 7 | TABLE ACCESS FULL| TMP_FOO | 8168 | 207K| | 10 |
| 8 | TABLE ACCESS FULL| FOO | 7188 | 245K| | 9 |
| 9 | TABLE ACCESS FULL | BAR | 409 | 5317 | | 1 |
| 10 | TABLE ACCESS FULL | GEE | 4084 | 89848 | | 5 |
----------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
据我所知,索引存在并且是正确的.我有什么选择让Oracle 9i使用它们?
更新#1: TMP_FOO是一个临时表,在此测试中没有行.FOO是一个常规表,在我的本地XE中有13,035行; 不确定为什么查询计划显示1,也许它意识到针对空表的INNER JOIN不需要全表扫描: - ?
更新#2:我花了几周时间尝试所有内容,没有提供真正的增强功能:查询重写,优化器提示,数据库设计更改,删除临时表...最后,我得到了相同的9.2副本客户拥有的.0.1.0未打补丁的Oracle版本(具有明显的架构差异),在我的网站上安装它......惊喜!在我的9i中,所有执行计划都会立即生效,查询需要1到10秒才能完成.
此时,我几乎确信客户存在严重的错误配置问题.
看起来你要么没有10g express数据库的数据,要么你的统计数据没有正确收集.在任何一种情况下,它都会向Oracle看起来没有很多行,因此索引范围扫描是合适的.
在您的9i数据库中,统计信息看起来像是正确收集的,Oracle看到一个包含大量行且没有where子句的4表连接.在这种情况下,由于您没有提供提示,Oracle会使用默认的ALL_ROWS优化程序行为构建解释计划:Oracle将找到将所有行返回到最后行的最高性能的计划.在这种情况下,具有全表扫描的HASH JOIN是非常有效的,它将使用索引NESTED LOOP连接更快地返回大的行集.
也许您想使用索引,因为您只对查询的前几行感兴趣.在这种情况下,使用提示/*+ FIRST_ROWS*/将帮助Oracle了解您对第一行响应时间比总体查询时间更感兴趣.
也许您想使用索引,因为您认为这会导致更快的总查询时间.您可以通过使用类似的提示来强制执行解释计划USE_NL,USE_HASH但大多数情况下您会看到,如果统计信息是最新的,则优化程序将选择最有效的计划.
更新:我看到您关于TMP_FOO的更新是一个没有行的临时表.临时表的问题是它们没有统计信息,因此我的上述答案不能完全适用于临时表.由于临时表没有统计数据,因此Oracle必须进行猜测(这里它选择了非常随意的8168行),这导致计划效率低下.
这种情况可能适合使用提示.你有几个选择:
| 归档时间: |
|
| 查看次数: |
1110 次 |
| 最近记录: |