oracle学习笔记9: model子句(下)

物化视图

--物化视图与查询重写
DROP MATERIALIZED VIEW mv_model_inventory;
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 sequential order(
   inventory[year,week] order by year, week=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 sequential order(
     inventory[year,week] order by year, week=nvl(inventory[cv(year),cv(week)-1],0)-sale[cv(year),cv(week)]+receipts[cv(year),cv(week)]
  )
)
WHERE country IN ('Australia') AND product='Xtend Memory'
ORDER BY product,country,year,week;

执行计划
----------------------------------------------------------
Plan hash value: 2344724570

----------------------------------------------------------------------------------------------------

| Id  | Operation                     | Name               | Rows  | Bytes | Cost (%CPU)| Time     |

----------------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT              |                    |    96 | 10944 |   278   (2)| 00:00:04 |

|   1 |  SORT ORDER BY                |                    |    96 | 10944 |   278   (2)| 00:00:04 |

|*  2 |   MAT_VIEW REWRITE ACCESS FULL| MV_MODEL_INVENTORY |    96 | 10944 |   277   (2)| 00:00:04 |

----------------------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("MV_MODEL_INVENTORY"."COUNTRY"='Australia' AND
              "MV_MODEL_INVENTORY"."PRODUCT"='Xtend Memory')

并行

基于model的sql语句可以与oracle的并行执行能力无缝结合。并行和基于model的sql语句可以改善分区表的查询性能。

SELECT /*+ parallel ( sf 4) */  
  product,country, year,week,inventory,sale,receipts
  from sales_fact 
  WHERE country IN ('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=nvl(inventory[cv(year),cv(week)-1],0)-sale[cv(year),cv(week)]+receipts[cv(year),cv(week)]
  )

model子句执行中的分区

分区表可以改进model sql语句的性能。如果model sql中的分区列与表的分区键相匹配,分区就是被剪裁过的。分区裁剪是一门将扫描限制在较少分区中的性能优化技术。

--分区剪裁
SELECT *
  FROM (SELECT product, country, YEAR, week, inventory, sale, receipts
          FROM sales_fact sf 
          model RETURN updated rows 
          PARTITION BY(YEAR, country) 
          dimension BY(product, week) 
          measures(0 inventory, sale, receipts) 
          rules AUTOMATIC ORDER(
          inventory [ product, week ] ORDER BY product, week =
                  nvl(inventory [ cv(product), cv(week) - 1 ], 0) - sale [ cv(product),
                  cv(week) ] + +receipts [ cv(product),
                  cv(week) ]))
 WHERE YEAR = 2000
   AND country = 'Australia'
   AND product = 'Xtend Memory'

--不进行分区剪裁
SELECT * FROM (
       SELECT product, country, year, week, inventory, sale, receipts
          FROM sales_fact sf 
          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 =
                  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'


执行计划
----------------------------------------------------------
Plan hash value: 463616151

----------------------------------------------------------------------------------

| Id  | Operation           | Name       | Rows  | Bytes | Cost (%CPU)| Time |

----------------------------------------------------------------------------------

|   0 | SELECT STATEMENT    |            |   154 | 17556 |   310   (1)| 00:00:04 |

|*  1 |  VIEW               |            |   154 | 17556 |   310   (1)| 00:00:04 |

|   2 |   SQL MODEL ACYCLIC |            |   154 |  8624 |            | |

|*  3 |    TABLE ACCESS FULL| SALES_FACT |   154 |  8624 |   310   (1)| 00:00:04 |

----------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("YEAR"=2000)
   3 - filter("PRODUCT"='Xtend Memory' AND "COUNTRY"='Australia')

product列和country列作为分区列,但表使用year列作为分区键,执行计划中的第1步表明为证year=2000由于规则可能访问其它分区而没有推进到视图中,因为year是一个维度列。因为分区键没有前推进视图中,就不允许进行分区剪裁,从而需要扫描所有分区。

索引

选择索引来提高使用model子句的sql语句性能与选择索引提高其它的任何sql语句的性能都是一样的。可以使用访问和筛选谓语确定最佳的索引策略。

--记住sql数据访问索引
SELECT * FROM (
       SELECT product, country, year, week, inventory, sale, receipts
          FROM sales_fact sf 
          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 =
                  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'

执行计划
----------------------------------------------------------
Plan hash value: 918126316

-----------------------------------------------------------------------------------------------

| Id  | Operation                     | Name          | Rows  | Bytes | Cost (%CPU)| Time     |

-----------------------------------------------------------------------------------------------

|   0 | SELECT STATEMENT              |               |   154 | 17556 |   139(0)| 00:00:02 |

|*  1 |  VIEW                         |               |   154 | 17556 |   139(0)| 00:00:02 |

|   2 |   SQL MODEL ACYCLIC           |               |   154 |  8624 |   |          |

|   3 |    TABLE ACCESS BY INDEX ROWID| SALES_FACT    |   154 |  8624 |   139(0)| 00:00:02 |

|*  4 |     INDEX RANGE SCAN          | SALES_FACT_I1 |   154 |       |     4(0)| 00:00:01 |

-----------------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("YEAR"=2000)
   4 - access("COUNTRY"='Australia' AND "PRODUCT"='Xtend Memory')

子查询因子

在商务环境中,需求是很复杂的并且经常需要多个层级的聚合。当书写复杂查询时,将子查询因子化与model子句结合起来,以避免sql语句变得复杂而不易管理。

--记住更多sql数据访问索引的内容
WITH t1 AS (
       SELECT product, country, year, week, inventory, sale, receipts
          FROM sales_fact sf 
          WHERE country IN ('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 =
                  nvl(inventory [ cv(year), cv(week) - 1 ], 0)
                   -sale [ cv(year), cv(week) ] 
                   +receipts [ cv(year),cv(week) ])
)
SELECT product, country, year, week, inventory, sale, receipts, prev_sale
FROM t1
MODEL RETURN UPDATED ROWS
PARTITION BY(product,country)
DIMENSION BY(year,week)
MEASURES (inventory,sale,receipts,0 prev_sale)
RULES SEQUENTIAL ORDER(
 prev_sale[year,week] ORDER BY year,week =
  NVL(sale[cv(year)-1,cv(week)],0)  
)
ORDER BY 1,2,3,4;

小结

写sql语句以集合的思维方式思考,很多sql语句都可以使用model子句来简洁地进行重写。用model子句或分析函数进行查询重写可以获取比传统的sql语句好得多的性能。子查询因子化,model和分析函数特性的结合可以用来有效实现复杂的需求。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容