database - Oracle:为什么在基础 View 中的数据更改后我的 MW 无效为 NEEDS_COMPILE 状态

标签 database oracle views materialized-views

我们正在使用以下物化 View 和底层 View 来实现一些报告。物化 View 完全由我们的应用程序手动刷新(通过 DBMS_SNAPSHOT.REFRESH( '"OVERALL_WEEKLY"','C');)。在此调用之后, View 处于 FRESH 状态,但在对基础表执行任何 DML 操作之后,物化 View 将获得 NEEDS_COMPILE 状态。 View 的查询如下。 未更新的表 EBR_CYCLE_TIME 和 EBR_AREA 变化非常频繁。因此,提交时刷新不是我们的目的。

有什么办法可以避免进入 NEEDS_COMPILE 状态吗?或者更好的是什么导致了 NEED_COMPILE 状态?

CREATE OR REPLACE FORCE VIEW "OTD_WEEKLY" AS
  SELECT
    otd.WEEK,
    otd.SITE_ID,
    otd.AREA_ID,
    otd.OTD_METRIC                                               AS CT_METRIC,
    ROUND(100 * (SUM(otd.SUCCESS) / SUM(otd.CT_TOTAL_COUNT)), 2) AS OTD_VALUE
  FROM
    (SELECT
       FC.MFL_FISCAL_YR_NUM * 100 + FC.MFL_FISCAL_WK_NUM AS WEEK,
       r.BUSINESS_UNIT_ID                                AS PAL2_ID,
       a.site_id                                         AS SITE_ID,
       a.area_def_id                                     AS AREA_ID,
       a.PRIORITY                                        AS PRIORITY,
       r.EBR_BUILD_SUBTYPE                               AS NPI,
       r.CORPORATE_TD                                    AS CTD,
       ctd.NAME                                          AS OTD_METRIC,
       COUNT(r.ebr_number)                               AS CT_TOTAL_COUNT,
       COUNT(
           CASE
           WHEN (ct.TIME_ELAPSED) > (ct.TARGET * 86400)
             THEN NULL
           ELSE r.ebr_number
           END)                                          AS SUCCESS,
       COUNT(
           CASE
           WHEN (ct.TIME_ELAPSED) > (ct.TARGET * 86400)
             THEN r.ebr_number
           ELSE NULL
           END)                                          AS MISSED,
       COUNT(DISTINCT r.ebr_number)                      AS TOTAL_NUMBER_OF_EBR
     FROM ebr_cycle_time ct
       JOIN ebr_area a
         ON (a.id = ct.ebr_area_id
             AND ct.status = 'FINISHED'
             AND a.ship_date IS NOT NULL)
       JOIN ebr_request r
         ON (a.ebr_id = r.id AND r.submit_date >= to_date((select STRING_VALUE from EBR_STATUS_TABLE where key = 'REPORT_DATE_FROM'),'DD.MM.YY'))
       JOIN EBR_GROUP_CYCLE_TIME_DEF gctd
         ON (ct.CYCLE_TIME_GROUP_DEF = gctd.ID)
       JOIN EBR_CYCLE_TIME_DEF ctd
         ON (ctd.ID = gctd.CYCLE_TIME_DEF_ID
             AND ctd.OTD_METRIC = 'Y')
       JOIN EBR_CYCLE_TIME_GROUP ctg
         ON (ctg.id = gctd.CYCLE_TIME_GROUP_ID)
       JOIN EEBR_MC_LCL_FISCAL FC
         ON (FC.MFL_QUERY_DT = TRUNC(a.ship_date) AND fc.MFL_QUERY_DT > add_months(trunc(sysdate, 'MM'), -8) AND fc.MFL_QUERY_DT <= sysdate)
     GROUP BY
       r.BUSINESS_UNIT_ID,
       a.site_id,
       a.area_def_id,
       ctd.name,
       fc.mfl_fiscal_yr_num,
       fc.mfl_fiscal_wk_num,
       ct.target,
       a.PRIORITY,
       r.CORPORATE_TD,
       r.EBR_BUILD_SUBTYPE
    ) otd
  GROUP BY
    otd.WEEK,
    otd.PAL2_ID,
    otd.SITE_ID,
    otd.AREA_ID,
    otd.OTD_METRIC;


CREATE OR REPLACE FORCE VIEW "LAGGING_SCORE_WEEKLY" AS
  SELECT
    dsc.SITE_ID,
    dsc.AREA_ID,
    dsc.CT_METRIC,
    (dsc.ARCHIVE_YEAR * 100 + dsc.ARCHIVE_WEEK) AS WEEK,
    ROUND(AVG(SCORE), 4)                        AS SCORE
  FROM
    (SELECT
       cts.site_id                                         AS SITE_ID,
       ls.AREA_DEF_ID                                      AS AREA_ID,
       ctd.name                                            AS CT_METRIC,
       ctd.id                                              AS CT_ID,
       fc.MFL_QUERY_DT                                     AS ARCHIVE_DAY,
       fc.MFL_FISCAL_WK_NUM                                AS ARCHIVE_WEEK,
       fc.MFL_FISCAL_MTH_NUM                               AS ARCHIVE_MONTH,
       fc.MFL_FISCAL_YR_NUM                                AS ARCHIVE_YEAR,
       (fc.MFL_FISCAL_YR_NUM * 100 + fc.MFL_FISCAL_WK_NUM) AS WEEK,
       CASE
       WHEN SUM(cts.PENALTY) > 0
         THEN SUM(cts.PENALTY)
       ELSE 0
       END                                                 AS EBR_PENALTY,
       COUNT(DISTINCT cts.ebr_number)                      AS NUMBER_OF_EBR,
       COUNT(DISTINCT (
         CASE
         WHEN cts.LAGGING_TIME > 0
           THEN cts.ebr_number
         ELSE NULL
         END))                                             AS NUMBER_OF_LAGGING_EBR,
       CASE
       WHEN SUM(cts.PENALTY) > 0
         THEN greatest(100 - 100 * (SUM(cts.PENALTY) / COUNT(DISTINCT cts.ebr_number)), 0)
       ELSE 100
       END                                                 AS SCORE
     FROM EBR_CYCLE_TIME_SNAPSHOT cts
       JOIN EBR_REQUEST r
         ON (r.ebr_number = cts.ebr_number AND r.submit_date >= to_date((select STRING_VALUE from EBR_STATUS_TABLE where key = 'REPORT_DATE_FROM'),'DD.MM.YY'))
       RIGHT JOIN EBR_LAGGING_STATISTIC ls
         ON ((TRUNC(ls.stat_date) = TRUNC(cts.SNAPSHOT_TIME))
             AND ls.site_id = cts.site_id
             AND cts.AREA_DEF_ID = ls.AREA_DEF_ID
             AND ls.CT_DEF_ID = cts.CYCLE_TIME_DEF_ID)
       JOIN EBR_CYCLE_TIME_DEF ctd
         ON (ls.CT_DEF_ID = ctd.id
             AND ctd.OTD_METRIC = 'Y')
       JOIN EEBR_MC_LCL_FISCAL fc
         ON (TRUNC(ls.STAT_DATE) = TRUNC(fc.MFL_QUERY_DT) AND fc.MFL_QUERY_DT > add_months(trunc(sysdate, 'MM'), -8))
     GROUP BY
       cts.site_id,
       ls.AREA_DEF_ID,
       ctd.name,
       ctd.id,
       fc.MFL_QUERY_DT,
       fc.MFL_FISCAL_WK_NUM,
       fc.MFL_FISCAL_MTH_NUM,
       fc.MFL_FISCAL_YR_NUM,
       ls.NUMBER_OF_EBR,
       ls.NUMBER_OF_LAGGING_EBR,
       TRUNC(ls.STAT_DATE)
    ) dsc
  GROUP BY dsc.SITE_ID,
    dsc.AREA_ID,
    dsc.CT_METRIC,
    dsc.ARCHIVE_WEEK,
    dsc.ARCHIVE_MONTH,
    dsc.ARCHIVE_YEAR;


CREATE OR REPLACE FORCE VIEW "START_COMPLIANCE_WEEKLY" AS
  SELECT
    'Starts Compliance'                                        AS CT_METRIC,
    a.site_id                                                 AS SITE_ID,
    a.area_def_id                                             AS AREA_ID,
    ((lstw.MFL_FISCAL_YR_NUM * 100) + lstw.MFL_FISCAL_WK_NUM) AS WEEK,
    ROUND(AVG(
              CASE
              WHEN ((ct.START_DATE IS NOT NULL
                     AND TRUNC((ct.START_DATE AT TIME ZONE 'MST') AT TIME ZONE s.time_zone) >
                         TRUNC((a.FIRST_FIRM_START_DATE AT TIME ZONE 'MST') AT TIME ZONE s.time_zone))
                    OR (ct.START_DATE IS NULL
                        AND next_day(TRUNC(sysdate) - 7, 'Sun') >
                            TRUNC((a.FIRST_FIRM_START_DATE AT TIME ZONE 'MST') AT TIME ZONE s.time_zone)))
                THEN 0
              ELSE 100
              END), 2)                                        AS SCORE
  FROM ebr_area a
    JOIN ebr_request r
      ON (a.ebr_id = r.id AND a.FIRST_FIRM_START_DATE IS NOT NULL
          AND a.FIRST_FIRM_START_DATE <= next_day(TRUNC(sysdate) - 7, 'Sun') AND AND r.status <> 'CANCELLED'
          AND r.submit_date >= to_date((select STRING_VALUE from EBR_STATUS_TABLE where key = 'REPORT_DATE_FROM'),'DD.MM.YY'))
    JOIN ebr_site s
      ON (s.id = a.site_id)
    LEFT JOIN
    (SELECT
       ct.START_DATE  AS START_DATE,
       ct.ROUND       AS ROUND,
       ct.ebr_area_id AS area_id
     FROM ebr_cycle_time ct
       JOIN EBR_GROUP_CYCLE_TIME_DEF gctd
         ON (ct.CYCLE_TIME_GROUP_DEF = gctd.ID
             AND ct.status <> 'NEW')
       JOIN EBR_CYCLE_TIME_DEF ctd
         ON (ctd.ID = gctd.CYCLE_TIME_DEF_ID
             AND ctd.code = 'SITE_PROCESSING')
    ) ct ON (ct.area_id = a.id)
    JOIN EEBR_MC_LCL_FISCAL lstw
      ON (lstw.MFL_QUERY_DT = TRUNC(FIRST_FIRM_START_DATE) AND lstw.MFL_QUERY_DT > add_months(trunc(sysdate, 'MM'), -8))
  GROUP BY
    a.site_id,
    s.time_zone,
    a.area_def_id,
    lstw.MFL_FISCAL_YR_NUM,
    lstw.MFL_FISCAL_WK_NUM;


CREATE MATERIALIZED VIEW "OVERALL_WEEKLY"
  AS SELECT s.code AS SITE_CODE,
  s.name      AS SITE_NAME,
  reports.SITE_ID,
  ad.NAME AS AREA,
  ad.CODE AS AREA_CODE,
  reports.AREA_ID,
  reports.REPORT_TYPE,
   reports.CT_METRIC,
  reports.WEEK,
  reports.SCORE
FROM (
  (SELECT 'Starts Compliance' AS REPORT_TYPE,
    AREA_ID,
    SITE_ID,
    CT_METRIC,
    WEEK,
    SCORE
  FROM START_COMPLIANCE_WEEKLY
  )
UNION
  (SELECT 'OTD' AS REPORT_TYPE,
    AREA_ID,
    SITE_ID,
    OTD_WEEKLY.CT_METRIC,
    OTD_WEEKLY.WEEK,
    OTD_WEEKLY.OTD_VALUE AS SCORE
  FROM OTD_WEEKLY
  )
UNION
  (SELECT 'Lagging' AS REPORT_TYPE,
    AREA_ID,
    SITE_ID,
    LAGGING_SCORE_WEEKLY.CT_METRIC,
    LAGGING_SCORE_WEEKLY.WEEK,
    LAGGING_SCORE_WEEKLY.SCORE
  FROM LAGGING_SCORE_WEEKLY
  )) reports
JOIN EBR_SITE s
ON (s.id = reports.SITE_ID)
JOIN EBR_AREA_DEF ad
ON (ad.id = reports.area_id);

最佳答案

这是预期的行为。 NEEDS_COMPILE 状态表示 MView 数据与源数据不同。它仅供引用。如果 refresh on commit 不适合您的使用,那么您可以忽略处于 NEEDS_COMPILE 状态的 MViews。

请参阅 MOS 文档 ID 264036.1:

Dependencies related to MVs are automatically maintained to ensure correct operation. When an MV is created, the materialized view depends on the master tables referenced in its definition. Any DML operation, such as an INSERT, or DELETE, UPDATE, or DDL operation on any dependency in the materialized view will cause it to become invalid.

关于database - Oracle:为什么在基础 View 中的数据更改后我的 MW 无效为 NEEDS_COMPILE 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39573247/

相关文章:

spring - 如何在 JPA 中创建日期规范以查找更大/更少等?

sql - 奇怪的 Oracle SQL "Invalid Identifier"错误

使用 to_date 的 Oracle 日期比较不起作用

ruby-on-rails - Rails 中的分析 View

sql - 需要有关 SQL 查询的帮助

database - 以有意义的方式可视化出勤数据

java - 查询C3P0启动时获取的连接数

sql - 物化 View : How to automatically refresh it upon table data changes?

oracle - 为什么在创建这个简单的实体化 View 示例时会出现 ORA-12054 错误?

database - 如何知道查询中是否检索到行 | Clickhouse 和 Golang