簡體   English   中英

Oracle - 物化視圖或表

[英]Oracle - materialized view or table

我有一個表(在Oracle 12c中)到目前為止有2200萬條記錄,每天還有10,000條記錄。 我們需要基於此表的計數,例如:

select col1, col2, count(*) cnt from my_table group by col1, col2;

此查詢將返回少於30行,並且col1col2的組合將是唯一的。

我們的應用程序需要檢查CNT頻繁價值,但的近似值CNT不夠好。 這意味着我們可以創建物化視圖並每10-20分鍾刷新一次。

物化視圖是否適合此要求,還是應該為其創建常規表?

提前致謝!!!

至少有三種不同的方法可以實現這一目標:

  1. 快速刷新物化視圖快速刷新物化視圖可能是理想的解決方案。 插入10,000行將產生少量開銷,但不需要重建任何東西; 每次提交后立即可以使用新的總計,並且檢索新的總計將非常快。 缺點是快速刷新物化視圖很難設置,並且有很多奇怪的陷阱。 它們適用於您的示例模式,但可能無法用於更復雜的方案。

    示例模式

     drop table my_table; create table my_table( id number not null, col1 number not null, col2 number not null, constraint my_table_pk primary key (id) ); insert into my_table select level, mod(level, 30), mod(level+1, 30) from dual connect by level <= 100000; begin dbms_stats.gather_table_stats(user, 'MY_TABLE'); end; / 

    創建物化視圖日志和物化視圖

     create materialized view log on my_table with rowid(col1, col2) including new values; create materialized view my_table_mv refresh fast on commit enable query rewrite as select col1, col2, count(*) total from my_table group by col1, col2; 

    查詢重寫

    靜默修改示例查詢以使用小物化視圖而不是大表。

     explain plan for select col1, col2, count(*) cnt from my_table group by col1, col2; select * from table(dbms_xplan.display); Plan hash value: 786752524 -------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 30 | 300 | 3 (0)| 00:00:01 | | 1 | MAT_VIEW REWRITE ACCESS FULL| MY_TABLE_MV | 30 | 300 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------------------- 
  2. 壓縮B *樹索引如果只有30個唯一值,則索引應該壓縮得很好並且不占用太多空間。 然后索引可以在快速全索引掃描中使用,並且像瘦表一樣。 此方法至少需要一個值不為null。 如果兩者都可以為null,那么基於函數的索引在這里可能很有用。

     create index my_table_idx on my_table(col1, col2) compress; 
  3. 圖索引當存在少量不同值時,位圖索引很小且很快。 但是,它們可能會為某些類型的DML引入災難性的鎖定問題。

     create bitmap index my_table_idx on my_table(col1, col2); 

根據您的方法的近似程度,您還可以嘗試SAMPLE子句:

select col1,
       col2,
       count(*) cnt
from   my_table sample(1)
group by col1, col2;

根據值的數據分布,這可能會給出合理的估計。 您可以測試您需要多少數量以獲得合理的結果,但除非使用block子句,否則很少值得超過4或5:

select col1,
       col2,
       count(*) cnt
from   my_table sample block(10)
group by col1, col2;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM