我正在运行以下查询:
SELECT * FROM all_tab_cols c
LEFT JOIN all_varrays v ON c.owner = v.owner
AND c.table_name = v.parent_table_name
AND c.column_name = v.parent_table_column
在 10g 服务器上这需要大约 2 秒,在 9i 上这需要 819 秒(13 分钟)!究竟是什么导致了这种巨大的性能差异,我该如何解决?
我正在运行以下查询:
SELECT * FROM all_tab_cols c
LEFT JOIN all_varrays v ON c.owner = v.owner
AND c.table_name = v.parent_table_name
AND c.column_name = v.parent_table_column
在 10g 服务器上这需要大约 2 秒,在 9i 上这需要 819 秒(13 分钟)!究竟是什么导致了这种巨大的性能差异,我该如何解决?
差异的一种可能解释是数据字典统计信息。在 10g 中,Oracle 引入了DBMS_STATS.GATHER_DICTIONARY_STATS() 过程,它针对 SYS 和 SYSTEM 模式(以及其他一些模式)收集统计信息。对数据字典进行统计可以改进针对数据库视图的某些查询的执行计划。
即使您运行 DBMS_STATS.GATHER_DATABASE_STATS(),它仍然会收集数据字典的统计信息,除非您将gather_sys
参数显式设置为false
.
您可以使用以下查询检查已针对 10g 数据库运行了哪些统计信息收集操作:
SQL> select * from DBA_OPTSTAT_OPERATIONS
2 order by start_time asc
3 /
OPERATION TARGET
---------------------------------------------------------------- ----------------
START_TIME
---------------------------------------------------------------------------
END_TIME
---------------------------------------------------------------------------
gather_database_stats(auto)
10-APR-10 06.00.03.953000 +01:00
10-APR-10 06.18.21.281000 +01:00
<snip/>
gather_database_stats(auto)
03-MAY-10 22.00.05.734000 +01:00
03-MAY-10 22.03.08.328000 +01:00
gather_dictionary_stats
06-MAY-10 13.48.49.839000 +01:00
06-MAY-10 13.57.42.252000 +01:00
10 rows selected.
SQL>
事实证明,默认情况下,9i 没有关于系统表的统计信息,而 10g+ 有。这就是导致性能差异的原因 - Oracle 不知道它应该如何正确加入它。