oracle sql 高级编程学习笔记(二十三)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/whandgdh/article/details/82712189

继上一篇中讲到model子句的性能优化,本文将继续学习model子句查询重写的优化:

一、谓语前推

1、实例演示:

select * from (select product, country, year, week, inventory, sale, receipts
  from sales_fact
     model return updated rows 
   partition by(product, country)
   dimension by(year, week)
   measures(0 inventory, sale, receipts) 
   rules automatic order
   (inventory [ year, week ] order by year,week asc   
    = nvl(inventory [ cv(year), cv(week) - 1 ], 0) - sale [ cv(year), cv(week) ] + receipts [ cv(year), cv(week) ]
   )  
 order by product, country, year, week)
 where 
--把谓词放到视图外面,看执行计划是否能进行谓词推进
         country = 'Australia'
   and product = 'Xtend Memory';

这里写图片描述
很明显第四步中两个谓词都推进了视图中,先进行了谓词筛选,然后在结果集中应用了model子句,
这样相对于model子句是非常小的数据行集

2 、没有进行谓词推进

我们把上一步中的谓词改为year=’2000’


select * from (select product, country, year, week, inventory, sale, receipts
  from sales_fact
     model return updated rows 
   partition by(product, country)
   dimension by(year, week)
   measures(0 inventory, sale, receipts) 
   rules automatic order
   (inventory [ year, week ] order by year,week asc   
    = nvl(inventory [ cv(year), cv(week) - 1 ], 0) - sale [ cv(year), cv(week) ] + receipts [ cv(year), cv(week) ]
   )  
 order by product, country, year, week)
 where   year='2000';

这里写图片描述
第四部中并没有进行谓词筛选,二十全表扫描得到111k行数据,model子句需要处理这些数据后
再进行谓词筛选

二、物化视图重写

一般来说分区列上的的谓词都可以安全地推进到视图中,但并不是所有维度列上的谓词都可以进行推进;
–创建物化视图

create materialized view mv_model_inventory 
 enable query  rewrite as
--可以查询重写
 select product, country, year, week, inventory, sale, receipts
  from sales_fact
     model return updated rows 
   partition by(product, country)
   dimension by(year, week)
   measures(0 inventory, sale, receipts) 
   rules automatic order
   (inventory [ year, week ] order by year,week asc   
    = nvl(inventory [ cv(year), cv(week) - 1 ], 0) - sale [ cv(year), cv(week) ] + receipts [ cv(year), cv(week) ]
   )  ;

查看查询:

select * from (select product, country, year, week, inventory, sale, receipts
  from sales_fact
     model return updated rows 
   partition by(product, country)
   dimension by(year, week)
   measures(0 inventory, sale, receipts) 
   rules automatic order
   (inventory [ year, week ] order by year,week asc   
    = nvl(inventory [ cv(year), cv(week) - 1 ], 0) - sale [ cv(year), cv(week) ] + receipts [ cv(year), cv(week) ]
   )  
  )
 where country = 'Australia'
   and product = 'Xtend Memory';

这里写图片描述

可以看到sql访问的是刚刚创建的物化视图,而不是sales_fact表,这样重写提高了sql语句的性能,因为物化视图
对规则进行了预求解并存储了结果

注意:包含model子句的物化视图不适用快速增量刷新
model 子句与oracle的并行执行能力实现无缝结合,并行和基于model的sql语句可以改善
分区表的查询性能。

三、并行

select /*+parallel(sf,4)*/product, country, year, week, inventory, sale, receipts
  from sales_fact sf
  where country = 'Australia'
   and product = 'Xtend Memory'
     model return updated rows 
   partition by(product, country)
   dimension by(year, week)
   measures(0 inventory, sale, receipts) 
   rules automatic order
   (  inventory [ year, week ] order by year,week asc   
    = nvl(inventory [ cv(year), cv(week) - 1 ], 0) - sale [ cv(year), cv(week) ] + receipts [ cv(year), cv(week) ]
   );

这里写图片描述

执行计划中可以看到 优化器分配了两组并行执行机来执行所列出的语句
第一组进行表读取,第二组进行model规则求解。

四、分区

重建表并按时create table SALES_FACT
(
country VARCHAR2(40) not null,
region VARCHAR2(30) not null,
product VARCHAR2(50) not null,
year NUMBER(4) not null,
week NUMBER(2) not null,
sale NUMBER,
receipts NUMBER
)
PARTITION BY LIST (year)
(
PARTITION SALES_FACT_PART_1998 VALUES (1998) ,
PARTITION SALES_FACT_PART_1999 VALUES (1999) ,
PARTITION SALES_FACT_PART_2000 VALUES (2000) ,
PARTITION SALES_FACT_PART_2001 VALUES (2001)
);分区

select * from (select year, product, country , week, inventory, sale, receipts
  from  SALES_FACT 
  where country = 'Australia'
   and product = 'Xtend Memory'
     model return updated rows 
   partition by(year, country)
--这里分区只能把year 加上
--维度列 不能再是year,不然会报列重复错误
   dimension by(product, week)
   measures(0 inventory, sale, receipts) 
   rules automatic order
   (  inventory [ product, week ] order by product,week asc   
    = nvl(inventory [ cv(product), cv(week) - 1 ], 0) - sale [ cv(product), cv(week) ] + receipts [ cv(product), cv(week) ]
   ))
   where   country = 'Australia'
   and product = 'Xtend Memory'
   and year=2000;
   ;

这里写图片描述
看到分区裁剪使得只分文分区3 Pstart 3 Pstop 3表示处理的分区范围开始和结束都是id=3的单个分区, 这是由model子句
作为分区列并且指定了year=2000谓语。还能看到的是执行计划中的谓词并没有year:=2000
select * from (select year, product, country , week, inventory, sale, receipts
from SALES_FACT
where country = ‘Australia’
and product = ‘Xtend Memory’
model return updated rows
partition by(product, country)
dimension by(year, week)
measures(0 inventory, sale, receipts)
rules automatic order
( inventory [ year, week ] order by year,week asc
= nvl(inventory [ cv(year), cv(week) - 1 ], 0) - sale [ cv(year), cv(week) ] + receipts [ cv(year), cv(week) ]
))
where year=2000 and country = ‘Australia’
and product = ‘Xtend Memory’ ;
这里写图片描述
可以看到执行计划扫描分区范围是从1到4 等于是全表扫描,并且再最后一步中再进行谓词year=2000的筛选
year 是维度列,并没有推进到最开始的表扫描中,虽然year是表sales_fact的分区键,但他没有推进视图中,就不能进行分区裁剪
只能进行全表扫描。

当然也可以指定访问的分区

select * from (select year, product, country , week, inventory, sale, receipts
  from  SALES_FACT  partition (SALES_FACT_PART_2000)
--指定访问year=2000的分区
  where country = 'Australia'
   and product = 'Xtend Memory'
     model return updated rows 
   partition by(product, country)
   dimension by(year, week)
   measures(0 inventory, sale, receipts) 
   rules automatic order
   (  inventory [ year, week ] order by year,week asc   
    = nvl(inventory [ cv(year), cv(week) - 1 ], 0) - sale [ cv(year), cv(week) ] + receipts [ cv(year), cv(week) ]
   ))
   where   year=2000 and  country = 'Australia'
   and product = 'Xtend Memory' ;

这里写图片描述
可以看到访问的分区范围只是id=3这个分区,但不同的是year因为是维度列,还是不能推进视图中。

猜你喜欢

转载自blog.csdn.net/whandgdh/article/details/82712189
今日推荐