我有一个经典的 Oracle 视图,称为
STAFFACTIVE
,其中包含大约 9500 行,每行 10 个小型本机数据类型字段(仅限数字和 varchar2(100))。
该视图基于来自 DBLINK 的 2 个表构建。
运行时间不到一秒。
我有另一个名为
DEPT_STAFFACTIVE
的视图,其中包含大约 350 行,每行 3 个字段(1 个数字和 2 个 varchar(100))。该视图基于来自本地模式的 1 个表 构建。
几毫秒内运行。
我创建了一个连接这两个视图的视图,没问题。运行时间为 ± 3 秒:
CREATE OR REPLACE FORCE VIEW V_STAFF
(
ID,
LOGIN,
FIRSTNAME,
LASTNAME,
SEARCH_FIRSTNAME,
SEARCH_LASTNAME,
PROPER_FIRSTNAME,
PROPER_LASTNAME,
EMAIL
)
BEQUEATH DEFINER
AS
SELECT pers_id AS id,
logn_login AS login,
rich_first_name AS firstname,
rich_family_name AS lastname,
search_first_name AS search_firstname,
search_family_name AS search_lastname,
INITCAP (rich_first_name) AS proper_firstname,
INITCAP (rich_family_name) AS proper_lastname,
email
FROM staffactive LEFT JOIN dept_staffactive ON staffactive.pers_id = dept_staffactive.pers_id;
但由于 3 秒有点太慢,我想使用 TABLE 或 MATERIALIZED VIEW 来代替。
问题:如果尝试
CREATE TABLE T_STAFF as SELECT * FROM V_STAFF
或者,如果我尝试基于 select * from V_STAFF 创建物化视图,那么 它会运行超过一分钟。
在语句中写JOIN时也会出现同样的问题
create table t_staff as select * from staffactive left join dept_staffactive on staffactive.pers_id = dept_staffactive.pers_id
有什么理由吗?哪里慢了?有没有工具可以分析这个?
我知道基于 2 个底层视图
V_FINAL
和 STAFFACTIVE
构建视图 DEPT_STAFFACTIVE
有点奇怪,但由于它们已经存在,为什么不使用它们呢?
你的物化视图实际上是在创建一个表(一个堆段),写入本地数据库。每当您写入数据库(DML 或 CTAS)时,Oracle 都必须使本地数据库成为驱动站点(并且它将忽略使用
driving_site
提示更改此设置的尝试)。
这意味着 Oracle 无法将本地表中的行
DEPT_STAFFACTIVE
发送到远程端以进行远程哈希联接。相反,它必须将远程 STAFFACTIVE
数据拉到本地并在本地执行连接。如果由于视图复杂性而无法估计行数,则可能会认为移动该数据的成本太大,而是选择嵌套循环操作,该操作将一次又一次地为中的每一行执行视图代码DEPT_STAFFACTIVE.
鉴于这些视图的尺寸很小,这可能就是它正在做的事情。
我建议暗示强制进行哈希连接:
create table t_staff as
select /*+ no_merge(staffactive) no_merge(dept_staffactive) use_hash(staffactive dept_staffactive) */ *
from staffactive left join dept_staffactive on staffactive.pers_id = dept_staffactive.pers_id