oracle 查询改写

阅读目录

  • oracle里的查询转换的作用
  •  4.2 子查询展开
  • 4.3 视图合并
    • 4.3.1 简单视图合并
    • 4.3.2  外连接视图合并
    •  4.3.3 复杂视图合并
  •  4.4  星型转换
  •  4.5  连接谓词推入
  • 4.6  连接因式分解
  •  4.7  表扩展
  •  4.8  表移除
  •  4.9  Oralce如何处理SQL语句中的IN
    • 4.9.1  IN-List Iterator
    • 4.9.2  IN-List Expansion/OR Expansion
    • 4.9.3  IN-List Filter
    • 4.9.4  对IN做子查询展开/视图合并

 

情形2:

先将子查询转换为内嵌视图,然后和外部查询中的表、视图做表连接:

oracle 查询改写-每日运维 View Code

 

 

 

 oracle对包含视图的目标SQL做简单视图合并也是有前提条件的,该SQL所包含视图的视图定义SQL语句中一定不能出现如下内容(包括但不限于):

  • 集合运算符(UNION,UNION ALL, INITERSECT,MINUS)
  • CONNECT BY 子句
  • ROWNUM
  • .......

不能做视图合并的例子:

oracle 查询改写-每日运维

create or replace view SH.view_1_union as select T2.PROD_ID
from sh.SALES t2 join sh.CUSTOMERS t3 on t2.CUST_ID=t3.CUST_ID where t3.CUST_GENDER='MALE' union all select PROD_ID from sh.sales t2 where t2.amount_sold1000; oracle 查询改写-每日运维oracle 查询改写-每日运维 View Code

 

4.3.2  外连接视图合并

外连接视图合并是指针对那些使用了外连接,以及所带视图的视图定义SQL语句中不包含distinct、group by等聚合函数的目标SQL的视图合并。这里“使用外连接”的含义是指外部查询的表和视图之间使用了外连接,或者该视图的视图定义SQL语句中使用了外连接。

关于外连接视图合并有一个很常用的限制,即当目标视图在和外部查询的表做外连接时,该目标视图可以做外连接视图合并的前提条件是,

  1. 要么该视图被作为外连接的驱动表,
  2. 要么该视图虽然被作为外连接的被驱动表但它的视图定义SQL语句中只包含一个表。 

 4.3.3 复杂视图合并

指针对那些所带视图的视图定义SQL语句中含有group by或distinct的目标SQL的视图合并。

意味着把其定义SQL语句拆开,并把其中的基表拿出来和外部查询中的表合并。这通常意味着上述视图定义SQL语句中的group by或distinct操作会被推迟执行,也就是说,这种情况下通常会先做表连接,再做group by或distinct操作,而不是像未做复杂视图合并时那样先在视图内部做完group by或distinct操作,然后才和外部查询中的表做表连接。

例子:

oracle 查询改写-每日运维

create view view_3 as select CUST_ID,PROD_ID,sum(QUANTITY_SOLD) as total from sh.sales group by CUST_ID,PROD_ID;;

select /+merge(t3)/t1.CUST_ID,t1.CUST_LAST_NAME from sh.CUSTOMERS t1
join view_3 t3 on t1.CUST_ID=t3.CUST_ID join sh.PRODUCTS t2 on t2.PROD_ID=t3.CUST_ID where t3.TOTAL>700 and t2.PROD_CATEGORY='Hardware' and t1.CUST_YEAR_OF_BIRTH=1977 and t1.CUST_MARITAL_STATUS='married'; oracle 查询改写-每日运维oracle 查询改写-每日运维 View Code

下面是没做视图合并

oracle 查询改写-每日运维 View Code

 

回到顶部

 4.4  星型转换

它的核心是将原星型连接中针对各个维度表的限制条件,通过等价改写的方式以额外的子查询施加到事实表上,然后通过对事实表上各连接列上已存在的位图索引间的位图操作(如按位与、按位或等),来达到有效减少事实表上待访问的数据量,避免对事实表做全表扫描的目的,这就可以有效缩短原SQL的执行时间,提高其执行效率。

例子:

123456 select /*cs1*/ t2.CUST_CITY, sum (t1.AMOUNT_SOLD)  as AMOUNT_SOLD_total from sh.SALES t1 ,sh.CUSTOMERS t2,sh.PRODUCTS t3,sh.CHANNELS t4  where t1.CUST_ID=t2.CUST_ID  and t1.PROD_ID=t3.PROD_ID  and t1.CHANNEL_ID=t4.CHANNEL_ID  and t2.COUNTRY_ID=52771  and t3.PROD_NAME= 'Mouse Pad' and t4.CHANNEL_DESC= 'Internet' group by t2.CUST_CITY

oracle 查询改写-15

oracle 查询改写-16