sql - 如果 MV 使用 ASNI Join,查询重写会失败

标签 sql oracle sql-execution-plan materialized-views

我无法获取 select 语句(下面脚本中的最后一行)来查询重写以使用物化 View 。不幸的是,我没有 REWRITE_TABLE,因此无法使用 dbms_view.explain_rewrite。我正在使用执行计划来确认它没有被重写以使用物化 View 。所有参数(参数显示在以下脚本末尾附近)和子句似乎都已到位。即使使用了REWRITE提示,它仍然没有重写。我缺少什么?预先感谢您。

drop table A;

create table A
  (
    x number not null
    , y char(1 byte) not null
  )
;

insert into A (x, y) select level, chr(mod(level-1,10) + ascii('A')) 
  from dual connect by level <= 1000
;

create unique index IU_A_x ON A (x);
create index IX_A_y ON A (y);

alter table A 
  add (
    constraint PK_A primary key ( x )
      rely
      using index IU_A_x
      enable validate
  )
;

--analyze table statistics for A

drop table B;

create table B
  (
    x number not null
    , z char(1 byte) not null
  )
;
  
insert into B (x, z) select mod(level,1000)+1, chr(mod(level-1,26) + ascii('A')) 
  from dual connect by level <= 1000000
;

create index IX_B_x ON B (x);
create index IX_B_z ON B (z);

alter table B 
  add (
    constraint R_B_x foreign key ( x )
      references A (x)
      rely
      enable validate
  )
;

--analyze table statistics for B

drop materialized view MV;

create materialized view MV 
  (
    y
    , z
  )
  build immediate
  refresh force on demand
  with primary key
    using trusted constraints
  enable query rewrite
  as 
  select
    A.y, B.z from A join B on A.x = B.x
;

create index IX_MV_y ON MV (y);
create index IX_MV_z ON MV (z);

--analyze table statistics for MV

set serveroutput on;
show parameters optimizer_mode; --all_rows
show parameters query_rewrite_enabled; -- true
show parameters query_rewrite_integrity; --enforced
select /*+ rewrite */ A.y, B.z from A join B on A.x = B.x where y = 'A' and z = 'Z';

最佳答案

我无法真正解释原因,但我的观察可以让您解决问题。

这是 explain_mviewMV查询的结果

exec dbms_mview.explain_mview(q'[select A.y, B.z from A join B on A.x = B.x]');

SELECT capability_name, possible, SUBSTR(related_text,1,8)
AS rel_text, SUBSTR(msgtxt,1,60) AS msgtxt
FROM MV_CAPABILITIES_TABLE
WHERE capability_name   like '%REWRITE%'
ORDER BY seq;

CAPABILITY_NAME                P REL_TEXT MSGTXT                                                      
------------------------------ - -------- ------------------------------------------------------------
REWRITE                        Y                                                                      
REWRITE_FULL_TEXT_MATCH        Y                                                                      
REWRITE_PARTIAL_TEXT_MATCH     Y                                                                      
REWRITE_GENERAL                N          the reason why the capability is disabled has escaped analys
REWRITE_PCT                    N          general rewrite is not possible or PCT is not possible on an

IMO 中的问题是 REWRITE_GENERAL = 'N'

如果仅使用 POJO(= Oracle 中的普通旧联接)重复相同的 explain_mview,您将看到不同的结果。

truncate table mv_capabilities_table;
exec dbms_mview.explain_mview(q'[select A.y, B.z from A, B where A.x = B.x]');

CAPABILITY_NAME                P REL_TEXT MSGTXT                                                      
------------------------------ - -------- ------------------------------------------------------------
REWRITE                        Y                                                                      
REWRITE_FULL_TEXT_MATCH        Y                                                                      
REWRITE_PARTIAL_TEXT_MATCH     Y                                                                      
REWRITE_GENERAL                Y                                                                      
REWRITE_PCT                    N          general rewrite is not possible or PCT is not possible on an
PCT_TABLE_REWRITE              N A        relation is not a partitioned table                         
PCT_TABLE_REWRITE              N B        relation is not a partitioned table

再次重要的是`REWRITE_GENERAL = 'Y'。

请注意,我使用的是 18.4 XE,这非常可疑,应该通过 Oracle 支持进行澄清。

最后的好消息是,如果您使用Oracle join定义MV,您可以使用ASNI join,您将看到重写:

示例

create materialized view MV2 
  enable query rewrite
  as 
  select
    A.y, B.z from A, B where A.x = B.x

EXPLAIN PLAN  SET STATEMENT_ID = 'jara1' into   plan_table  FOR
select   A.y, B.z from A join B on A.x = B.x where y = 'A' and z = 'Z'
;
  
SELECT * FROM table(DBMS_XPLAN.DISPLAY('plan_table', 'jara1','ALL'));

-------------------------------------------------------------------------------------
| Id  | Operation                    | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |      |  3846 | 15384 |   456   (8)| 00:00:01 |
|*  1 |  MAT_VIEW REWRITE ACCESS FULL| MV2  |  3846 | 15384 |   456   (8)| 00:00:01 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("MV2"."Z"='Z' AND "MV2"."Y"='A')

关于sql - 如果 MV 使用 ASNI Join,查询重写会失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66403519/

相关文章:

sql - 如何根据出现的列序列提取行

sql - 优化在同一表上使用多个左连接的查询

sql - HSQL 2.2.4,错误的查询计划

oracle - 在 Oracle 10g 中通过数据库链接复制元数据

sql - P/L SQL 中如何只转首字母大写其他字母小写?

oracle - 如何在使用 DBMS_SCHEDULER.CREATE_JOB 创建的作业中运行复杂的 PL/SQL 代码

performance - 为什么执行计划包括对持久化的计算列的用户定义函数调用?

sql - 如何在ORACLE中显示包中的功能代码?

sql - varchar 值的转换溢出了 int 列

ios - 低效的CoreData IN查询