存在外連接的物化視圖


ORACLE中的物化(實體)視圖[http://blog.sina.com.cn/s/blog_4b05c12a0100qm89.html]

 

 

 物化視圖是包括一個查詢結果的數據庫對像,它是遠程數據的的

本地副本,或者用來生成基於數據表求和的彙總表。物化視圖存儲基

於遠程表的數據,也可以稱爲快照。

 

 物化視圖可以查詢表,視圖和其它的物化視圖。

 

 通常情況下,物化視圖被稱爲主表(在複製期間)或明細表(在

數據倉庫中)。

 

 對於複製,物化視圖允許你在本地維護遠程數據的副本,這些副本

是隻讀的。如果你想修改本地副本,必須用高級複製的功能。當你想

從一個表或視圖中抽取數據時,你可以用從物化視圖中抽取。

 

 對於數據倉庫,創建的物化視圖通常情況下是聚合視圖,單一表

聚合視圖和連接視圖。

 

本篇我們將會看到怎樣創建物化視圖並且討論它的刷新選項。

 

 在複製環境下,創建的物化視圖通常情況下主鍵,rowid,和子查詢

視圖。

 

1.主鍵物化視圖:

 

 下面的語法在遠程數據庫表emp上創建主鍵物化視圖

 

 SQL> CREATE MATERIALIZED VIEW mv_emp_pk

 

 REFRESH FAST START WITH SYSDATE

 

 NEXT SYSDATE + 1/48

 

 WITH PRIMARY KEY

 

 

 AS SELECT * FROM emp@remote_db;

 

 Materialized view created.

 

 注意:當用FAST選項創建物化視圖,必須創建基於主表的視

圖日誌,如下:

 

 SQL> CREATE MATERIALIZED VIEW LOG ON emp;

 

 Materialized view log created.

 

2.Rowid物化視圖

 

 下面的語法在遠程數據庫表emp上創建Rowid物化視圖

 

 SQL> CREATE MATERIALIZED VIEW mv_emp_rowid

 

 REFRESH WITH ROWID

 

 AS SELECT * FROM emp@remote_db;

 

 Materialized view log created.

 

3.子查詢物化視圖

 

 下面的語法在遠程數據庫表emp上創建基於emp和dept表的

子查詢物化視圖

 

 SQL> CREATE MATERIALIZED VIEW mv_empdept

 

 AS SELECT * FROM emp@remote_db e

 

 WHERE EXISTS

 

 (SELECT * FROM dept@remote_db d

 

 WHERE e.dept_no = d.dept_no)

 

 Materialized view log created.

 

 REFRESH 子句

 

 

 [refresh [fast|complete|force]

 

 [on demand | commit]

 

 [start with date] [next date]

 

 [with {primary key|rowid}]]

 

 

 

 Refresh選項說明:

 

a. oracle用刷新方法在物化視圖中刷新數據.

 

b. 是基於主鍵還是基於rowid的物化視圖

 

c. 物化視圖的刷新時間和間隔刷新時間

 

 

 

Refresh方法-FAST子句

 

 增量刷新用物化視圖日誌(參照上面所述)來發送主表已經修改

的數據行到物化視圖中.如果指定REFRESH FAST子句,那麼應該對

主表創建物化視圖日誌

 

 SQL> CREATE MATERIALIZED VIEW LOG ON emp;

 

Materialized view log created.

 

 對於增量刷新選項,如果在子查詢中存在分析函數,則物化視圖

不起作用。

 

 

 

Refresh方法- COMPLETE子句

 

 完全刷新重新生成整個視圖,如果請求完全刷新,oracle會完成

完全刷新即使增量刷新可用。

 

 

 

 

Refresh Method – FORCE 子句

 

 當指定FORCE子句,如果增量刷新可用Oracle將完成增量刷新,

否則將完成完全刷新,如果不指定刷新方法(FAST, COMPLETE, or

FORCE),Force選項是默認選項

 

 

 

主鍵和ROWD子句

 

 WITH PRIMARY KEY選項生成主鍵物化視圖,也就是說物化視圖

是基於主表的主鍵,而不是ROWID(對應於ROWID子句). PRIMARY

KEY是默認選項,爲了生成PRIMARY KEY子句,應該在主表上定義

主鍵,否則應該用基於ROWID的物化視圖.

 

 主鍵物化視圖允許識別物化視圖主表而不影響物化視圖增量刷新

的可用性。

 

 Rowid物化視圖只有一個單一的主表,不能包括下面任何一項:

 

 Distinct  或者聚合函數.

 

 Group by ,子查詢,連接和SET操作

 

 

 

刷新時間

 

 START WITH子句通知數據庫完成從主表到本地表第一次複製的

時間,應該及時估計下一次運行的時間點, NEXT 子句說明了刷新的

間隔時間.

 

 SQL> CREATE MATERIALIZED VIEW mv_emp_pk

 

 

 REFRESH FAST

 

 START WITH SYSDATE

 

 NEXT SYSDATE + 2

 

 WITH PRIMARY KEY

 

 AS SELECT * FROM emp@remote_db;

 

 Materialized view created.

 

在上面的例子中,物化視圖數據的第一個副本在創建時生成,以後每

兩天刷新一次.

 

 

 

總結

 

物化視圖提供了可伸縮的基於主鍵或ROWID的視圖,指定了刷新方

法和自動刷新的時間。

 

 

 

 

 

物化視圖的效率

 

有兩個表:人員表A001有10萬數據,機構表B001有5千數據

 

建普通視圖:

 

create or replace view test_v as

select * from A001 a ,B001 B where a.a001721=b.orguid

 

建一個物化視圖

 

 

create MATERIALIZED view test_v_m as

select * from A001 a ,B001 B where a.a001721=b.orguid

 

比較效率:

 

select * from test_v where A001001 like '%軍%' or

b001003 like '1006%' or A001011 like '70%' ;用

時10秒多

 

from test_v_m where A001001 like '%軍%' or b001003 like

'1006%' or A001011 like '70%' ;用時0.125秒

 

對查詢來說,物化視圖的效率是普通視圖的10/0.125=80倍;相

當高啊!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

創建多表關聯的實體化視圖

 

某些實體化視圖包含多表關聯,但不包含聚合操作

 

(例如sum())

 

例如

 

Example 8-4

 

實體化視圖是在 sales 表和times,customers 三張表的關聯的基礎上

創建的。創建這種類型的實體化視圖的好處是預先處理了代價高昂

的關聯操作。在任意類型的 DML操作之後,使用fast refresh 的方

式來刷新僅包含表關聯的實體化視圖是可以實現的。

 

僅包含表關聯的實體化視圖同樣支持在兩種情況下刷新:

 

 ON COMMIT 和 ON DEMAND.在 ON COMMIT 下,當基表發生

DML操作並提交commit 的時候,實體化視圖被刷新。

 

Oracle不允許實體化視圖中有self-jions 的存在。

 

假如指定刷新方式爲

 

REFRESH FAST, oracle 執行附加的校驗,以確定fast refresh能被執

行。這些附加的檢查包括:

 

1 每個基表下必須創建相應的 materialized view log

 

2 每個基表的rowid 必須在實體化視圖的select 語句中出現

 

3如果存在外聯接,在where 子句不能有任何的selections.並且,所

有的關聯必須以 AND 相連,並且用 “=”操作符。

 

4如果存在外聯接,唯一性約束必須存在於外聯的 inner table 的相關

列中。

 

 

爲了提高刷新的速度,必須在實體化視圖上創建基表的 rowed 所在

列的索引。

 

 

 

Example 8-4 Materialized View Containing Only Joins

 

 

 

CREATE MATERIALIZED VIEW LOG ON sales

 

 

 

WITH ROWID;

 

 

 

CREATE MATERIALIZED VIEW LOG ON times

 

 

 

WITH ROWID;

 

 

 

CREATE MATERIALIZED VIEW LOG ON customers

 

 

 

WITH ROWID;

 

 

 

CREATE MATERIALIZED VIEW detail_sales_mv

 

PARALLEL BUILD IMMEDIATE

 

 

 

REFRESH FAST

 

 

 

 

AS

 

 

 

SELECT

 

 

 

s.rowid "sales_rid", t.rowid "times_rid", c.rowid "customers_rid",

 

 

 

c.cust_id, c.cust_last_name, s.amount_sold,

 

 

 

s.quantity_sold, s.time_id

 

 

 

FROM sales s, times t, customers c

 

WHERE s.cust_id = c.cust_id(+) AND s.time_id = t.time_id(+);

 

在這個示例中,爲了執行

 

fast refresh ,

 

唯一性約束必須存在於

 

c.cust_id and t.time_id.

 

必須創建

 

sales_rid, times_rid, and customers_rid

 

各自的索引,如此可以提高刷新的速度。

 

CREATE INDEX mv_ix_salesrid ON detail_sales_mv("sales_rid");

 

 

 

Materialized Views with Aggregates

 

 

 

 

創建聚合類型的實體化視圖。

 

 

 

在數據倉庫中,實體化視圖中經常會包括一些聚合操作。爲了能夠進

行快速刷新(fast refersh) ,在select 語句中必須包含所有在group by

 

中出現的列名,並且必須有一個count(*) ,所有在gorup by 中出現

的列都必須有一個 count(列名)出現在select 中。同樣,所有於實體

化視圖相關的表上都必須創建實體化和視圖日誌。有效的聚合函數包

括:

 

 

 

SUM

 

,

 

COUNT(x)

 

,

 

COUNT(*)

 

,

 

AVG

 

,

 

VARIANCE

 

,

 

STDDEV

 

,

 

 

MIN

 

, and

 

MAX ,

 

被聚合的值可以是任何的

 

sql

 

表達式。

 

Fast refresh

 

一個包含關聯和聚合的實體化視圖是可能的。但有如下限制:

 

1

 

 

 

實體化視圖中不能包含非複用的表達式

 

(

 

具有實時特徵的

 

) 。比如

 

 

 

SYSDATE and ROWNUM.

 

2

 

 

 

實體化視圖中不能包含

 

 

 

RAW or LONG 數據類型。

 

3

 

 

實體化視圖相關的表必須創建實體化視圖日誌,並且滿足如下條件

 

包含被實體化視圖引用到的所有的列。

 

指定

 

 

 

with rowed和INCLUDING NEW VALUES.

 

如果表的預期操作是

 

inserts/direct-loads, deletes, and updates的混合,指定SEQUENCE 子

句只用

 

 

 

SUM

 

,

 

COUNT

 

,

 

AVG

 

,

 

STDDEV

 

,

 

VARIANCE

 

,

 

MIN

 

 and

 

MAX

 

 

支持

 

 fast refresh.

 

對於每個聚合

 

 agg(expr),

 

必須相應寫一個

 

 count(expr)

 

與之對應

 

如果VARIANCE(expr)or STDDEV(expr)被指定,那麼

COUNT(expr)and SUM(expr) 必須被指定。Oracle推薦 SUM(expr

*expr) 也被指定。在

 

select列表中必須包含所有group by

 

中出現的列.如果實體化視圖有如下的一點,那麼fast refresh 只支持

常規DML inserts

 

和直接路徑的裝載

 

(

 

direct loads

 

)

 

 

 

a

 

 

 

實體化視圖包含MIN 或者 MAX

 

 

 

 

b 實體化視圖包含SUM(expr)

 

 但是沒有COUNT(expr)

 

 

 

c

 

實體化視圖中不包含

 

 COUNT(*)如上的實體化視圖稱之爲insert-only materialized view.

 

包含

 

MAX or MIN實體化視圖在delete或者混合的

 

DML

 

操作之後可以是 fast refresh,條件是視圖中沒有where 子句。

 

(10g

 

以上適用

 

)

 

如果沒有外聯接,在where 子句中可以包含有選擇性的條件和關聯

 

 如果實體化視圖中包含外聯接,fast refresh只支持在outer table 被

修改的情況。同樣,唯一性約束必須存在於

 

inner join table中。如果有外聯,所有的關聯條件都必須用 AND 連

接和必須用 = 操作符。

 

Example 8-1

 

Example 1: Creating a Materialized View

 

CREATE MATERIALIZED VIEW LOG ON products WITH

SEQUENCE, ROWID

 

 

(prod_id, prod_name, prod_desc, prod_subcategory,

prod_subcategory_desc,

 

prod_category, prod_category_desc, prod_weight_class,

prod_unit_of_measure,

 

 prod_pack_size, supplier_id, prod_status, prod_list_price,

prod_min_price)

 

INCLUDING NEW VALUES;

 

CREATE MATERIALIZED VIEW LOG ON sales

 

WITH SEQUENCE, ROWID

 

(prod_id, cust_id, time_id, channel_id, promo_id, quantity_sold,

amount_sold)

 

INCLUDING NEW VALUES;

 

CREATE MATERIALIZED VIEW product_sales_mv

 

PCTFREE 0

 

 

 

TABLESPACE demo

 

STORAGE (INITIAL 8k NEXT 8k PCTINCREASE 0)

 

BUILD IMMEDIATE

 

REFRESH FAST

 

ENABLE QUERY REWRITE

 

AS SELECT p.prod_name, SUM(s.amount_sold) AS dollar_sales,

 

COUNT(*) AS cnt, COUNT(s.amount_sold) AS cnt_amt

 

 

FROM sales s, products p

 

WHERE s.prod_id = p.prod_id GROUP BY p.prod_name;

 

Example 8-3 Example 3:

 

Creating a Materialized View

 

CREATE MATERIALIZED VIEW LOG ON sales WITH SEQUENCE,

ROWID

 

(prod_id, cust_id, time_id, channel_id, promo_id, quantity_sold,

amount_sold)

 

INCLUDING NEW VALUES;

 

CREATE MATERIALIZED VIEW sum_sales

 

PARALLEL

 

BUILD IMMEDIATE

 

 

 

REFRESH FAST ON COMMIT AS

 

 

 

SELECT s.prod_id, s.time_id, COUNT(*) AS count_grp,

 

 

 

SUM(s.amount_sold) AS sum_dollar_sales,

 

 

 

COUNT(s.amount_sold) AS count_dollar_sales,

 

 

 

SUM(s.quantity_sold) AS sum_quantity_sales,

 

 

 

 

COUNT(s.quantity_sold) AS count_quantity_sales

 

FROM sales s

 

GROUP BY s.prod_id, s.time_id;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章