Oracle中物化视图频繁刷新
Frequent refresh of materialized view in Oracle
我们正在优化性能,并希望创建基于少数表的连接的物化视图(数百万条记录)。此视图将用于在延迟不超过几 (3-5) 秒的情况下向用户显示文件夹中的文档。
我想应该是错位的MV,刷新间隔有几秒。
从数据库的角度来看,这是可以接受的解决方案吗?
视图将是这样的:
SELECT *
FROM documents this_
LEFT OUTER JOIN account_statements this_1_
ON this_.Id = this_1_.FK_Document
LEFT OUTER JOIN contracts this_2_ ON this_.Id = this_2_.FK_Document
LEFT OUTER JOIN pension_agreements this_3_
ON this_.Id = this_3_.FK_Contract
LEFT OUTER JOIN dead this_4_ ON this_.Id = this_4_.FK_Document
LEFT OUTER JOIN pay_orders this_5_ ON this_.Id = this_5_.FK_Document
LEFT OUTER JOIN pay_registers this_6_
ON this_.Id = this_6_.FK_Document
LEFT OUTER JOIN pocards this_7_ ON this_.Id = this_7_.FK_Document
LEFT OUTER JOIN ransom_agreements this_8_
ON this_.Id = this_8_.FK_Document
LEFT OUTER JOIN successor_statements this_9_
ON this_.Id = this_9_.FK_Document
INNER JOIN document_treenodes treenodes14_
ON this_.Id = treenodes14_.fk_document
INNER JOIN treenodes treenode2_
ON treenodes14_.fk_treenode = treenode2_.Id
LEFT OUTER JOIN registration_cards regcard1_
ON this_.fk_registration_card = regcard1_.Id
LEFT OUTER JOIN employees todirectem12_
ON regcard1_.to_direct = todirectem12_.Id
LEFT OUTER JOIN REG_CARD_STATUSES regcardsta11_
ON regcard1_.status = regcardsta11_.Id
LEFT OUTER JOIN filestorages filestorag10_
ON this_.fk_file = filestorag10_.Id
LEFT OUTER JOIN actions holdaction4_
ON this_.fk_hold = holdaction4_.Id
LEFT OUTER JOIN employees holdemploy5_
ON holdaction4_.fk_operator = holdemploy5_.Id
LEFT OUTER JOIN actions doneaction6_
ON this_.fk_done = doneaction6_.Id
LEFT OUTER JOIN employees doneemploy7_
ON doneaction6_.fk_operator = doneemploy7_.Id
LEFT OUTER JOIN actions signaction8_
ON this_.fk_signed = signaction8_.Id
LEFT OUTER JOIN employees signemploy9_
ON signaction8_.fk_operator = signemploy9_.Id
LEFT OUTER JOIN actions scanaction3_
ON this_.fk_scan = scanaction3_.Id
更新
瓶颈如下:
SELECT *
FROM documents this_
INNER JOIN document_treenodes treenodes14_ ON this_.Id = treenodes14_.fk_document
INNER JOIN treenodes treenode2_ ON treenodes14_.fk_treenode = treenode2_.Id
LEFT OUTER JOIN registration_cards regcard1_ ON this_.fk_registration_card = regcard1_.Id
WHERE (
regcard1_.status IS NULL OR
(
NOT (
regcard1_.status = 3 /* :p0 */)
AND
NOT (
regcard1_.status = 4 /* :p1 */)
)
)
AND
this_.fk_deleted IS NULL AND
(
this_.isdelete IS NULL OR
this_.isdelete = 0 /* :p2 */)
AND
treenode2_.Id = 1235 /* :p3 */ AND
this_.fk_done IS NULL AND
(
regcard1_.status IS NULL OR
NOT (
regcard1_.status = 1 /* :p4 */)
)
ORDER BY this_.Id DESC
OFFSET 0 ROWS
FETCH FIRST 50 /* :p5 */ ROWS ONLY
treenode2_.Id = 1235 /* :p3 */ AND
this_.fk_done IS NULL AND
(
regcard1_.status IS NULL OR
NOT (
regcard1_.status = 1 /* :p4 */)
)
ORDER BY this_.Id DESC
OFFSET 0 ROWS
FETCH FIRST 50 /* :p5 */ ROWS ONLY
计划是:
计划哈希值:3579815467
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 105K| 85M| | 50518 (1)| 00:00:04 |
|* 1 | VIEW | | 105K| 85M| | 50518 (1)| 00:00:04 |
|* 2 | WINDOW SORT PUSHED RANK | | 105K| 13M| 14M| 50518 (1)| 00:00:04 |
|* 3 | HASH JOIN RIGHT OUTER | | 105K| 13M| | 48503 (1)| 00:00:04 |
| 4 | INDEX FULL SCAN | REG_CARD_STATUSES_PK | 4 | 12 | | 1 (0)| 00:00:01 |
|* 5 | FILTER | | | | | | |
|* 6 | HASH JOIN RIGHT OUTER | | 105K| 13M| 4048K| 48502 (1)| 00:00:04 |
| 7 | TABLE ACCESS FULL | REGISTRATION_CARDS | 84317 | 3046K| | 171 (2)| 00:00:01 |
|* 8 | HASH JOIN | | 183K| 17M| 3936K| 47339 (1)| 00:00:04 |
|* 9 | INDEX FAST FULL SCAN| DOCUMENT_TREENODE_PK | 183K| 1788K| | 1872 (2)| 00:00:01 |
|* 10 | TABLE ACCESS FULL | DOCUMENTS | 5064K| 425M| | 24635 (2)| 00:00:02 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("from$_subquery$_010"."rowlimit_$$_rownumber"<=0+50 AND
"from$_subquery$_010"."rowlimit_$$_rownumber">0)
2 - filter(ROW_NUMBER() OVER ( ORDER BY INTERNAL_FUNCTION("THIS_"."ID") DESC )<=0+50)
3 - access("REGCARD1_"."STATUS"="REGCARDSTA11_"."ID"(+))
5 - filter(("REGCARD1_"."STATUS" IS NULL OR "REGCARD1_"."STATUS"<>3 AND
"REGCARD1_"."STATUS"<>4) AND ("REGCARD1_"."STATUS" IS NULL OR "REGCARD1_"."STATUS"<>1))
6 - access("THIS_"."FK_REGISTRATION_CARD"="REGCARD1_"."ID"(+))
8 - access("THIS_"."ID"="TREENODES14_"."FK_DOCUMENT")
9 - filter("TREENODES14_"."FK_TREENODE"=1235)
10 - filter("THIS_"."FK_DONE" IS NULL AND ("THIS_"."ISDELETE"=0 OR "THIS_"."ISDELETE" IS NULL)
AND "THIS_"."FK_DELETED" IS NULL)
我冒用了 'reformatting' 你的查询(顺便说一句:我认为那里有一点复制粘贴错误,有些部分在结尾处看起来翻了一番)
'layout' 对实际执行时间的影响为零,但它让我更容易理解你在做什么(只是因为我'我习惯了我自己的风格,我并不是说它更好,这只是我习惯的)
无论如何,如果我理解正确并且没有弄乱括号,那么这应该等同于您的查询:
SELECT *
FROM documents this_
INNER JOIN document_treenodes treenodes14_
ON treenodes14_.fk_document = this_.Id
INNER JOIN treenodes treenode2_
ON treenode2_.Id = treenodes14_.fk_treenode
AND treenode2_.Id = 1235 /* :p3 */
LEFT OUTER JOIN registration_cards regcard1_
ON regcard1_.Id = this_.fk_registration_card
WHERE this_.fk_deleted IS NULL
AND this_.fk_done IS NULL
AND (
this_.isdelete IS NULL OR this_.isdelete = 0 /* :p2 */
)
AND (
regcard1_.status IS NULL OR regcard1_.status NOT IN (3 /* :p0 */, 4 /* :p1 */, 1 /* :p4 */)
)
ORDER BY this_.Id DESC
OFFSET 0 ROWS
FETCH FIRST 50 /* :p5 */ ROWS ONLY
我怀疑此更改会产生很大的不同,但它可能会改变系统处理当前计划中步骤 8 和 9 的方式。值得一试=)
无论如何,我 'learned' 从查询中得到的是你似乎想要所有没有匹配 [registration_cards] 记录的记录,但如果有,那么它们不应该有状态 3 、4 或 1(分别为:p0、:p1、:p4)。
=> 这是否等同于说您想要所有没有匹配状态为 3、4 或 1 的 [registration_cards] 记录的 [documents] 记录?
SELECT *
FROM documents this_
INNER JOIN document_treenodes treenodes14_
ON treenodes14_.fk_document = this_.Id
INNER JOIN treenodes treenode2_
ON treenode2_.Id = treenodes14_.fk_treenode
AND treenode2_.Id = 1235 /* :p3 */
WHERE this_.fk_deleted IS NULL
AND this_.fk_done IS NULL
AND (
this_.isdelete IS NULL OR this_.isdelete = 0 /* :p2 */
)
AND NOT EXISTS ( SELECT *
FROM registration_cards regcard1_
WHERE regcard1_.Id = this_.fk_registration_card
AND regcard1_.status IN (3 /* :p0 */, 4 /* :p1 */, 1 /* :p4 */) )
ORDER BY this_.Id DESC
OFFSET 0 ROWS
FETCH FIRST 50 /* :p5 */ ROWS ONLY
假设[registration_card].Id是table的PK,或者status和Id字段有覆盖索引,这样可能会稍微快一些。就像我之前说过的,我的印象是大部分时间都在对结果集进行排序时迷失了方向,但话又说回来,我可能完全误解了解释计划。谷歌搜索实际上似乎告诉我 the explain plan is but guesswork and not 'the real deal'.. 叹息,有时我真的很可怜你可怜的 Oracle 用户 =P
我们正在优化性能,并希望创建基于少数表的连接的物化视图(数百万条记录)。此视图将用于在延迟不超过几 (3-5) 秒的情况下向用户显示文件夹中的文档。
我想应该是错位的MV,刷新间隔有几秒。
从数据库的角度来看,这是可以接受的解决方案吗?
视图将是这样的:
SELECT *
FROM documents this_
LEFT OUTER JOIN account_statements this_1_
ON this_.Id = this_1_.FK_Document
LEFT OUTER JOIN contracts this_2_ ON this_.Id = this_2_.FK_Document
LEFT OUTER JOIN pension_agreements this_3_
ON this_.Id = this_3_.FK_Contract
LEFT OUTER JOIN dead this_4_ ON this_.Id = this_4_.FK_Document
LEFT OUTER JOIN pay_orders this_5_ ON this_.Id = this_5_.FK_Document
LEFT OUTER JOIN pay_registers this_6_
ON this_.Id = this_6_.FK_Document
LEFT OUTER JOIN pocards this_7_ ON this_.Id = this_7_.FK_Document
LEFT OUTER JOIN ransom_agreements this_8_
ON this_.Id = this_8_.FK_Document
LEFT OUTER JOIN successor_statements this_9_
ON this_.Id = this_9_.FK_Document
INNER JOIN document_treenodes treenodes14_
ON this_.Id = treenodes14_.fk_document
INNER JOIN treenodes treenode2_
ON treenodes14_.fk_treenode = treenode2_.Id
LEFT OUTER JOIN registration_cards regcard1_
ON this_.fk_registration_card = regcard1_.Id
LEFT OUTER JOIN employees todirectem12_
ON regcard1_.to_direct = todirectem12_.Id
LEFT OUTER JOIN REG_CARD_STATUSES regcardsta11_
ON regcard1_.status = regcardsta11_.Id
LEFT OUTER JOIN filestorages filestorag10_
ON this_.fk_file = filestorag10_.Id
LEFT OUTER JOIN actions holdaction4_
ON this_.fk_hold = holdaction4_.Id
LEFT OUTER JOIN employees holdemploy5_
ON holdaction4_.fk_operator = holdemploy5_.Id
LEFT OUTER JOIN actions doneaction6_
ON this_.fk_done = doneaction6_.Id
LEFT OUTER JOIN employees doneemploy7_
ON doneaction6_.fk_operator = doneemploy7_.Id
LEFT OUTER JOIN actions signaction8_
ON this_.fk_signed = signaction8_.Id
LEFT OUTER JOIN employees signemploy9_
ON signaction8_.fk_operator = signemploy9_.Id
LEFT OUTER JOIN actions scanaction3_
ON this_.fk_scan = scanaction3_.Id
更新 瓶颈如下:
SELECT *
FROM documents this_
INNER JOIN document_treenodes treenodes14_ ON this_.Id = treenodes14_.fk_document
INNER JOIN treenodes treenode2_ ON treenodes14_.fk_treenode = treenode2_.Id
LEFT OUTER JOIN registration_cards regcard1_ ON this_.fk_registration_card = regcard1_.Id
WHERE (
regcard1_.status IS NULL OR
(
NOT (
regcard1_.status = 3 /* :p0 */)
AND
NOT (
regcard1_.status = 4 /* :p1 */)
)
)
AND
this_.fk_deleted IS NULL AND
(
this_.isdelete IS NULL OR
this_.isdelete = 0 /* :p2 */)
AND
treenode2_.Id = 1235 /* :p3 */ AND
this_.fk_done IS NULL AND
(
regcard1_.status IS NULL OR
NOT (
regcard1_.status = 1 /* :p4 */)
)
ORDER BY this_.Id DESC
OFFSET 0 ROWS
FETCH FIRST 50 /* :p5 */ ROWS ONLY
treenode2_.Id = 1235 /* :p3 */ AND
this_.fk_done IS NULL AND
(
regcard1_.status IS NULL OR
NOT (
regcard1_.status = 1 /* :p4 */)
)
ORDER BY this_.Id DESC
OFFSET 0 ROWS
FETCH FIRST 50 /* :p5 */ ROWS ONLY
计划是:
计划哈希值:3579815467
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 105K| 85M| | 50518 (1)| 00:00:04 |
|* 1 | VIEW | | 105K| 85M| | 50518 (1)| 00:00:04 |
|* 2 | WINDOW SORT PUSHED RANK | | 105K| 13M| 14M| 50518 (1)| 00:00:04 |
|* 3 | HASH JOIN RIGHT OUTER | | 105K| 13M| | 48503 (1)| 00:00:04 |
| 4 | INDEX FULL SCAN | REG_CARD_STATUSES_PK | 4 | 12 | | 1 (0)| 00:00:01 |
|* 5 | FILTER | | | | | | |
|* 6 | HASH JOIN RIGHT OUTER | | 105K| 13M| 4048K| 48502 (1)| 00:00:04 |
| 7 | TABLE ACCESS FULL | REGISTRATION_CARDS | 84317 | 3046K| | 171 (2)| 00:00:01 |
|* 8 | HASH JOIN | | 183K| 17M| 3936K| 47339 (1)| 00:00:04 |
|* 9 | INDEX FAST FULL SCAN| DOCUMENT_TREENODE_PK | 183K| 1788K| | 1872 (2)| 00:00:01 |
|* 10 | TABLE ACCESS FULL | DOCUMENTS | 5064K| 425M| | 24635 (2)| 00:00:02 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("from$_subquery$_010"."rowlimit_$$_rownumber"<=0+50 AND
"from$_subquery$_010"."rowlimit_$$_rownumber">0)
2 - filter(ROW_NUMBER() OVER ( ORDER BY INTERNAL_FUNCTION("THIS_"."ID") DESC )<=0+50)
3 - access("REGCARD1_"."STATUS"="REGCARDSTA11_"."ID"(+))
5 - filter(("REGCARD1_"."STATUS" IS NULL OR "REGCARD1_"."STATUS"<>3 AND
"REGCARD1_"."STATUS"<>4) AND ("REGCARD1_"."STATUS" IS NULL OR "REGCARD1_"."STATUS"<>1))
6 - access("THIS_"."FK_REGISTRATION_CARD"="REGCARD1_"."ID"(+))
8 - access("THIS_"."ID"="TREENODES14_"."FK_DOCUMENT")
9 - filter("TREENODES14_"."FK_TREENODE"=1235)
10 - filter("THIS_"."FK_DONE" IS NULL AND ("THIS_"."ISDELETE"=0 OR "THIS_"."ISDELETE" IS NULL)
AND "THIS_"."FK_DELETED" IS NULL)
我冒用了 'reformatting' 你的查询(顺便说一句:我认为那里有一点复制粘贴错误,有些部分在结尾处看起来翻了一番)
'layout' 对实际执行时间的影响为零,但它让我更容易理解你在做什么(只是因为我'我习惯了我自己的风格,我并不是说它更好,这只是我习惯的)
无论如何,如果我理解正确并且没有弄乱括号,那么这应该等同于您的查询:
SELECT *
FROM documents this_
INNER JOIN document_treenodes treenodes14_
ON treenodes14_.fk_document = this_.Id
INNER JOIN treenodes treenode2_
ON treenode2_.Id = treenodes14_.fk_treenode
AND treenode2_.Id = 1235 /* :p3 */
LEFT OUTER JOIN registration_cards regcard1_
ON regcard1_.Id = this_.fk_registration_card
WHERE this_.fk_deleted IS NULL
AND this_.fk_done IS NULL
AND (
this_.isdelete IS NULL OR this_.isdelete = 0 /* :p2 */
)
AND (
regcard1_.status IS NULL OR regcard1_.status NOT IN (3 /* :p0 */, 4 /* :p1 */, 1 /* :p4 */)
)
ORDER BY this_.Id DESC
OFFSET 0 ROWS
FETCH FIRST 50 /* :p5 */ ROWS ONLY
我怀疑此更改会产生很大的不同,但它可能会改变系统处理当前计划中步骤 8 和 9 的方式。值得一试=)
无论如何,我 'learned' 从查询中得到的是你似乎想要所有没有匹配 [registration_cards] 记录的记录,但如果有,那么它们不应该有状态 3 、4 或 1(分别为:p0、:p1、:p4)。 => 这是否等同于说您想要所有没有匹配状态为 3、4 或 1 的 [registration_cards] 记录的 [documents] 记录?
SELECT *
FROM documents this_
INNER JOIN document_treenodes treenodes14_
ON treenodes14_.fk_document = this_.Id
INNER JOIN treenodes treenode2_
ON treenode2_.Id = treenodes14_.fk_treenode
AND treenode2_.Id = 1235 /* :p3 */
WHERE this_.fk_deleted IS NULL
AND this_.fk_done IS NULL
AND (
this_.isdelete IS NULL OR this_.isdelete = 0 /* :p2 */
)
AND NOT EXISTS ( SELECT *
FROM registration_cards regcard1_
WHERE regcard1_.Id = this_.fk_registration_card
AND regcard1_.status IN (3 /* :p0 */, 4 /* :p1 */, 1 /* :p4 */) )
ORDER BY this_.Id DESC
OFFSET 0 ROWS
FETCH FIRST 50 /* :p5 */ ROWS ONLY
假设[registration_card].Id是table的PK,或者status和Id字段有覆盖索引,这样可能会稍微快一些。就像我之前说过的,我的印象是大部分时间都在对结果集进行排序时迷失了方向,但话又说回来,我可能完全误解了解释计划。谷歌搜索实际上似乎告诉我 the explain plan is but guesswork and not 'the real deal'.. 叹息,有时我真的很可怜你可怜的 Oracle 用户 =P