Tom*_*day 5 oracle materialized-views oracle12c
我们有一个高度(也许已经结束?)规范化的表来跟踪版本化的值。它只是插入,没有更新。
示例数据:
"ID" "Version" "Value"
1 0 "A_1"
2 0 "B_1"
1 1 "A_2"
3 0 "C_1"
Run Code Online (Sandbox Code Playgroud)
我们经常运行查询以仅提取每个 ID 的最新值。当我们处理数百万行时,我们开始遇到性能问题。我已经能够使用物化视图对改进进行原型设计,但无法以它们自刷新“ON COMMIT”的方式创建它们
到目前为止我得到的是这个(修改如下)
CREATE MATERIALIZED VIEW TABLE_LATEST
BUILD IMMEDIATE
REFRESH FAST
ON COMMIT AS
SELECT T.ID
,T.LAST_VERSION
FROM (
SELECT ID
,MAX(VERSION) OVER (PARTITION BY ID) LAST_VERSION
FROM TABLE
) T
GROUP BY T.ID, T.LAST_VERSION;
Run Code Online (Sandbox Code Playgroud)
由于反馈,现在对其进行了修订:
CREATE MATERIALIZED VIEW TABLE_LATEST
BUILD IMMEDIATE
REFRESH FAST
ON COMMIT AS
SELECT ID
,MAX(VERSION)
FROM TABLE
GROUP BY T.ID;
Run Code Online (Sandbox Code Playgroud)
哪个失败了:
ORA-12033: 无法在“SCHEMA”.“TABLE”上使用物化视图日志中的过滤器列
Run Code Online (Sandbox Code Playgroud)*Cause: The materialized view log either did not have filter columns logged, or the timestamp associated with the filter columns was more recent than the last refresh time. *Action: A complete refresh is required before the next fast refresh. Add filter columns to the materialized view log, if required.
如果我更改Refresh为Force并删除它,它只会“工作” On Commit。我不知道这是否属于物化视图的“无分析”规则,或者我是否首先错误地创建了日志?
CREATE MATERIALIZED VIEW LOG ON TABLE
LOGGING
WITH SEQUENCE, ROWID, (VALUE)
INCLUDING NEW VALUES;
Run Code Online (Sandbox Code Playgroud)
表架构:
CREATE TABLE "TABLE"
(
ID NUMBER(10, 0) NOT NULL
, VERSION NUMBER(10, 0) NOT NULL
, VALUE VARCHAR2(4000 CHAR)
, CONSTRAINT MASTERRECORDFIELDVALUES_PK PRIMARY KEY
(
ID
, VERSION
)
USING INDEX
(
CREATE UNIQUE INDEX TABLE_PK ON TABLE(ID ASC, VERSION ASC)
LOGGING
...
)
ENABLE
)
LOGGING
Run Code Online (Sandbox Code Playgroud)
我是否在正确的轨道上?是否有更好的方法来预先计算最新版本?或者我只需要拨入日志和查看设置?
如果您不需要与最新版本关联的值,那么您可以简单地执行以下操作:
CREATE MATERIALIZED VIEW LOG ON t1
LOGGING
WITH SEQUENCE, ROWID, (val)
INCLUDING NEW VALUES;
create materialized view t1_latest
refresh fast on commit
as
select id,
max(version) latest_version
from t1
group by id;
Run Code Online (Sandbox Code Playgroud)
可以在 Oracle LiveSQL 中找到此测试用例。
否则,您需要创建三个单独的 MV(因为您无法在提交时快速刷新涉及保持密集排名第一/最后的物化视图) - 根据http://www.sqlsnippets.com/en/topic-12926。 html - 像这样:
主表上的物化视图日志:
CREATE MATERIALIZED VIEW LOG ON t1
LOGGING
WITH SEQUENCE, ROWID, (val)
INCLUDING NEW VALUES;
Run Code Online (Sandbox Code Playgroud)
第一个物化视图:
create materialized view t1_sub_mv1
refresh fast on commit
as
select id,
max(version) latest_version,
count(version) cnt_version,
count(*) cnt_all
from t1
group by id;
Run Code Online (Sandbox Code Playgroud)
第一个物化视图上的物化视图日志:
create materialized view log on t1_sub_mv1
with rowid, sequence (id, latest_version, cnt_version, cnt_all)
including new values;
Run Code Online (Sandbox Code Playgroud)
第二个物化视图:
create materialized view t1_sub_mv2
refresh fast on commit
as
select id,
version,
max(val) max_val_per_id_version,
count(*) cnt_all
from t1
group by id,
version;
Run Code Online (Sandbox Code Playgroud)
第一个物化视图上的物化视图日志:
create materialized view log on t1_sub_mv2
with rowid, sequence (id, max_val_per_id_version, cnt_all)
including new values;
Run Code Online (Sandbox Code Playgroud)
第三个也是最后一个物化视图:
create materialized view t1_main_mv
refresh fast on commit
as
select mv1.id,
mv1.latest_version,
mv2.max_val_per_id_version val_of_latest_version,
mv1.rowid mv1_rowid,
mv2.rowid mv2_rowid
from t1_sub_mv1 mv1,
t1_sub_mv2 mv2
where mv1.id = mv2.id
and mv1.latest_version = mv2.version;
Run Code Online (Sandbox Code Playgroud)
可以在 Oracle LiveSQL 中找到对此的支持测试用例。