Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Ein Blick auf den Oracle Group-by-Bug

Oracle hat eine neue Funktion, Group by Elimination, für Abfragen eingeführt, bei denen die Group by-Spalte auch der eindeutige Schlüssel der Tabelle ist. Wie bei vielen neuen Funktionen wurden auch hier noch nicht alle Probleme gelöst. Das Problem entsteht, wenn Schlüsselwerte mit Funktionsaufrufen manipuliert werden. Das folgende Beispiel veranschaulicht das Problem, indem eine Tabelle mit einem DATE als Primärschlüssel verwendet wird und das Jahr durch Extrahieren mit TO_CHAR oder EXTRACT.

extrahiert wird

Eine Tabelle wird wie folgt erstellt:

create table bug_test_calendar(
        cal_name   char(17),
        bus_dt   date,
        updt_timestamp       timestamp (6) default systimestamp,
        constraint pk_bug_test_calendar 
                        primary key (bus_dt)
)
/

insert into bug_test_calendar (bus_dt)
select
        sysdate + 10 * rownum
from 
        all_objects 
where 
        rownum <= 40 
/

commit;

Wenn die unten gezeigte Abfrage ausgeführt wird, erzeugt sie die folgenden Ergebnisse:

select
        to_char(bus_dt,'YYYY') bus_dt, count(*) ct
from
       bug_test_calendar
group by 
        to_char(bus_dt,'YYYY')
order by 
        to_char(bus_dt,'YYYY')
/


BUS_DF   CT
-------  --
2020      1
2020      1
...
2020      1

40 rows returned

Oracle „weiß“ nicht, dass die Schlüsselwerte so manipuliert wurden, dass sie nicht mehr eindeutig sind, daher wendet der Optimierer die auf eindeutigen Schlüsseln basierende Group-By-Eliminierung mit weniger als herausragenden Ergebnissen an,

EXTRACT schneidet nicht besser ab und liefert die gleichen Ergebnisse. Dieses Verhalten wird durch den Parameter „_optimizer_aggr_groupby_elim“ gesteuert, der standardmäßig auf „true“ gesetzt ist. Da es sich um einen versteckten Parameter handelt, wird seine Einstellung von Oracle weder in der V$PARAMEter- noch in der V$SPPARAMETER-Ansicht gemeldet. Die Problemumgehung besteht darin, diesen Parameter einfach auf „false“ zu setzen. Die Aktivierung kann jedoch anderen Gruppieren-nach-Abfragen helfen, bei denen die eindeutigen Schlüsselwerte nicht manipuliert werden.

Geben Sie Oracle 19c ein, wo diese Funktionalität teilweise behoben ist:

select
        to_char(bus_dt,'YYYY') bus_dt, count(*) ct
from
       bug_test_calendar
group by 
        to_char(bus_dt,'YYYY')
order by 
        to_char(bus_dt,'YYYY')
/


BUS_DF   CT
-------  --
2020     40


Leider ist EXTRACT in 19c immer noch kaputt:

select
        to_char(bus_dt,'YYYY') bus_dt, count(*) ct
from
       bug_test_calendar
group by 
        extract(year deom bus_dt)
order by 
        extract(year deom bus_dt)
/


BUS_DF   CT
-------  ==
2020      1
2020      1
...
2020      1

40 rows returned

Offensichtlich würde eine Gruppieren-nach-Abfrage bei wirklich eindeutigen Schlüsselwerten eine Zählung von 1 für jeden Schlüssel erzeugen. Und ebenso offensichtlich sollte Oracle in der Lage sein, zu erkennen, wenn Werte nicht mehr eindeutig sind, und den richtigen Group-By-Mechanismus aufzurufen. Es bleibt abzuwarten, ob Versionen nach 19c die zweite Bedingung beheben und somit korrekte Ergebnisse liefern, ohne diese Funktion ausschalten zu müssen.

Dies betrifft möglicherweise nicht jede Installation von Oracle neuer als 12.1, aber es ist wichtig zu wissen, falls falsche Ergebnisse in ausgewählten Gruppen nach Abfragen angezeigt werden.

# # #

Siehe Artikel von David Fitzjarrell