2011-01-31 8 views
6

Tengo una tabla, demo_fact en Oracle 11g y tiene varias columnas virtuales definidas como tales:Oracle reescritura de consultas con columnas virtuales en la tabla de origen

ALTER TABLE demo_fact ADD (demo_measure_from_virtual NUMBER GENERATED ALWAYS AS 
    (CASE WHEN demo_category_column = 20 THEN demo_numericdata_column ELSE 0 END) 
    VIRTUAL VISIBLE); 

entonces tengo una vista materializada definida como

CREATE MATERIALIZED VIEW demo_agg_mv 
REFRESH FORCE ON DEMAND 
ENABLE QUERY REWRITE 
AS 
SELECT 
    demo_dim_one, 
    demo_dim_two, 
    SUM(demo_measure_from_virtual) demo_measure_from_virtual 
    FROM demo_fact 
    GROUP BY demo_dim_one, demo_dim_two 

Ahora quiero reescritura de consultas en arrancar en la siguiente consulta:

SELECT demo_dim_one, SUM(demo_measure_from_virtual) 
FROM demo_fact 
GROUP BY demo_dim_one 

pero no es así. Corrí en EXPLAIN_REWRITE y aquí está la salida:

QSM-01150: query did not rewrite 
QSM-01102: materialized view, DEMO_AGG_MV, requires join back to table, 
      DEMO_FACT, on column, DEMO_MEASURE_FROM_VIRTUAL 
QSM-01082: Joining materialized view, DEMO_AGG_MV, with table, DEMO_FACT, 
      not possible 
QSM-01102: materialized view, DEMO_AGG_MV, requires join back to table, 
      DEMO_FACT, on column, DEMO_NUMERICDATA_COLUMN 

Historia: Estoy haciendo esto con 70 millones de filas y 50 columnas virtuales (todos ellos tienen la misma estructura, la declaración simple caso anterior, pero con un diferente columna de comparación y una columna de resultados diferente)

Este problema parece manifestarse solo cuando la tabla de hechos tiene columnas virtuales, pero cambiarlas a no virtuales consumiría demasiado espacio de disco. ¿Por qué Oracle no está reescribiendo la consulta? ¿Que puedo hacer para arreglarlo?

Respuesta

2

No sé qué tan útil es para usted, pero Oracle requiere que todas las columnas que agrupan la vista materializada se incluyan en la declaración que se reescribirá. (edición al menos en conjunto con columnas virtuales. Esto es probablemente "no por diseño" ...)

Si intenta explain_rewrite en

select 
    demo_dim_one, 
    sum(s) 
from (
    select 
     demo_dim_one, 
     sum(demo_measure_from_virtual) s 
    from 
     demo_fact 
    group by 
     demo_dim_one, 
     demo_dim_two 
) 
group by demo_dim_one 

debería decir que se ha reescrito el consulta.

Esto se puede demostrar de esta manera:

una tabla a en el que se define la columna virtual:

create table tq84_virt_col (
    a varchar2(2), 
    b varchar2(2), 
    c number, 
    d number 
); 


insert into tq84_virt_col values ('A', 'X', 1, 1); 
insert into tq84_virt_col values ('A', 'X', 2, 1); 
insert into tq84_virt_col values ('A', 'Y', 3, 0); 
insert into tq84_virt_col values ('A', 'Y', 4, 1); 

insert into tq84_virt_col values ('B', 'Y', 11, 1); 
insert into tq84_virt_col values ('B', 'X', 12, 0); 
insert into tq84_virt_col values ('B', 'X', 13, 1); 

La definición de la columna virtual:

alter table tq84_virt_col add (
    virt_col number generated always as (
    case when d = 1 then c else 0 end 
) 
    virtual visible 
); 

El materializada ver. Nota: los grupos de columnas a y b:

create materialized view tq84_mat_view 
refresh force on demand 
enable query rewrite 
as 
select 
    a, b, 
    sum(virt_col) sum_virt_col 
from 
    tq84_virt_col 
group by 
    a,b 

El materializó no se usará la vista, como habrá observado:

begin 
    dbms_mview.explain_rewrite(
    'select a, sum(virt_col) from tq84_virt_col group by a' 
); 
end; 
/

select message 
from rewrite_table; 

QSM-01150: query did not rewrite 
QSM-01102: materialized view, TQ84_MAT_VIEW, requires join back to table, TQ84_VIRT_COL, on column, VIRT_COL 
QSM-01082: Joining materialized view, TQ84_MAT_VIEW, with table, TQ84_VIRT_COL, not possible 
QSM-01102: materialized view, TQ84_MAT_VIEW, requires join back to table, TQ84_VIRT_COL, on column, C 

Ahora, ambas columnas a y b son seleccionados y agrupados en (con una consulta externa para garantizar el mismo conjunto de resultados):

truncate table rewrite_table; 

begin 
    dbms_mview.explain_rewrite(
    'select a, sum(s) from (select a, sum(virt_col) s from tq84_virt_col group by a, b) group by a' 
); 
end; 
/

select message 
from rewrite_table; 

QSM-01151: query was rewritten 
QSM-01209: query rewritten with materialized view, TQ84_MAT_VIEW, using text match algorithm 
QSM-01219: no suitable materialized view found to rewrite this query 
+0

¡Gran explicación! Gracias por tomarse el tiempo. Desafortunadamente para mí, estoy trabajando con SAP BusinessObjects, así que esperaba usar una consulta no anidada. Marcaré esto como una respuesta aceptada para explicarlo tan bien y con prontitud. –

Cuestiones relacionadas