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