Vor längerer Zeit hatte ich erwähnt, dass die Verwendung von Queries mit subquery factoring (CTEs, WITH-Klauseln) als Datengrundlage für das SSAS-Prozessing oder auch für SSRS-Berichte den (nicht unbedingt selbsterklärenden) Fehler "ORA-32036: Nicht unterstützte Schreibweise für Inlining von Abfrage-Name in WITH-Klausel" hervorrufen kann. Dabei konnte man die Queries über sqlplus oder SQL Developer problemlos ausführen, aber beim Zugriff der Microsoft-Systeme ergaben sich die Probleme, die sich nur durch Refakturierung des Codes oder größere Umwege (z.B. die Definition entsprechender table functions) umgehen ließen.
Gestern ist mir ORA-32036 wieder begegnet: diesmal bei der Anlage einer Materialized View. Und in diesem Fall lässt sich das Verhalten sehr leicht reproduzieren:
-- Anlage von zwei - sehr simplen - Basistabellen create table test_base_mpr as select rownum id , mod(rownum, 2) col1 from dual connect by level <= 100; create table test_add_mpr as select rownum col1 from dual connect by level <= 10; create materialized view test_mpr as with basedata as ( select test_base_mpr.id , test_base_mpr.col1 from test_base_mpr left outer join test_add_mpr on (test_base_mpr.col1 = test_add_mpr.col1) ) , basedata_filtered as ( select * from basedata where id <= 50 ) , basedata_grouped as ( select col1 , count(*) count_id from basedata_filtered group by col1 ) select basedata_filtered.col1 , basedata_grouped.count_id from basedata_filtered left outer join basedata_grouped on basedata_filtered.col1 = basedata_grouped.col1 order by basedata_filtered.col1; FEHLER in Zeile 1: ORA-32036: Nicht unterstützte Schreibweise für Inlining von Abfrage-Name in WITH-Klausel -- wenn man die CTE basedata in eine inline-View umwandelt, gibt es keine Probleme: create materialized view test_mpr as with basedata_filtered as ( select * from (select test_base_mpr.id , test_base_mpr.col1 from test_base_mpr left outer join test_add_mpr on (test_base_mpr.col1 = test_add_mpr.col1) ) basedata where id <= 50 ) , basedata_grouped as ( select col1 , count(*) count_id from basedata_filtered group by col1 ) select basedata_filtered.col1 , basedata_grouped.count_id from basedata_filtered left outer join basedata_grouped on basedata_filtered.col1 = basedata_grouped.col1 order by basedata_filtered.col1; Materialized View wurde erstellt.
Auch in diesem Fall lässt sich die ursprüngliche Query via sqlplus problemlos ausführen (über die Semantik der Query und den Inhalt der Ergebnismenge - je 25 mal die Tupel (0, 25) und (1, 25) - muss man nicht weiter nachdenken). Auch kann man auf der Basis der Definition eine (nicht materialisierte) View anlegen. Aber die MV stellt offenbar ein Problem dar.
Beim Vergleich der Pläne für die SELECTs (inklusive "Column Projection Information") sehe ich - abgesehen von generierten Query-Block- und temp-table-transformation-Namen - keine Unterschiede. Dabei sollte das SQL der Query dem des MV-Aufbaus entsprechen: zumindest im Fall des erfolgreichen Aufbaus trifft dies zu, hier scheint nur das übliche
INSERT /*+ BYPASS_RECURSIVE_CHECK */ INTO "TEST"."TEST_MPR"
vor der Definitions-Query.
Mein Versuch, die exakten Voraussetzungen des Problems zu bestimmen, bleibt erst einmal unvollständig. Ursprünglich nahm ich an, dass die Verwendung einer CTE an mehreren Stellen der Query genügen würde, um den Fehler hervorzurufen, aber auch die funktionierende Version verwendet die CTE basedata_filtered als Basis für basedata_grouped und als Element des Outer Joins im Haupt-SELECT. Möglicherweise spielt tatsächlich nur die CTE-Verschachtelungstiefe eine Rolle. In jedem Fall ist das Problem ziemlich unerfreulich, da es dazu zwingt, den durch CTEs verständlich gegliederten SQL-Code wieder in eine Form zu bringen, die der CBO offenbar besser versteht - die aber für den Entwickler in vielen Fällen schwerer zu durchschauen sein dürfte. Falls mir (oder jemandem, der hier vorbei kommt) jenseits der Phänomenologie eine plausible Erklärung dazu einfällt, liefere ich sie nach.
Aus Gründen der Vollständigkeit hier auch noch mal der Link auf Dom Brooks Überlegungen zum Thema - interessant sind dort auch die Kommentare.
Keine Kommentare:
Kommentar veröffentlichen