Oracle
 sql >> Base de données >  >> RDS >> Oracle

Un regard sur le bogue Oracle Group-by

Oracle a introduit une nouvelle fonctionnalité, le groupe par élimination, pour les requêtes où le groupe par colonne est également la clé unique de la table. Comme pour de nombreuses nouvelles fonctionnalités, celle-ci n'a toujours pas résolu tous les problèmes. Le problème survient lorsque les valeurs clés sont manipulées avec des appels de fonction. L'exemple suivant illustrera le problème en utilisant une table avec une DATE comme clé primaire et en extrayant l'année est extraite à l'aide de TO_CHAR ou EXTRACT.

Un tableau est créé comme suit :

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;

Lorsque la requête ci-dessous est exécutée, elle produit les résultats suivants :

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 ne "sait" pas que les valeurs de clé ont été manipulées de sorte qu'elles ne sont plus uniques, donc l'optimiseur applique l'élimination groupée basée sur la clé unique avec des résultats moins que stellaires,

EXTRACT ne fait pas mieux, renvoyant les mêmes résultats. Ce comportement est contrôlé par le paramètre « _optimizer_aggr_groupby_elim », qui est défini sur true par défaut. Comme il s'agit d'un paramètre masqué, sa configuration n'est pas signalée par Oracle dans les vues V$PARAMEter ou V$SPPARAMETER. La solution de contournement consiste simplement à définir ce paramètre sur false. Cependant, l'activer peut aider d'autres requêtes groupées où les valeurs de clé uniques ne sont pas manipulées.

Entrez Oracle 19c, où cette fonctionnalité est partiellement corrigée :

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


Malheureusement, EXTRACT est toujours cassé en 19c :

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

De toute évidence, étant donné des valeurs de clé vraiment uniques, une requête groupée produirait un décompte de 1 pour chaque clé. Et, tout aussi évident, Oracle devrait être capable de reconnaître quand les valeurs ne sont plus uniques et d'invoquer le mécanisme de regroupement approprié. Il reste à voir si les versions après 19c corrigeront la deuxième condition et renverront ainsi des résultats corrects sans avoir à désactiver cette fonctionnalité.

Cela peut ne pas affecter toutes les installations d'Oracle plus récentes que 12.1, mais il est utile de savoir si des résultats erronés commencent à apparaître dans les requêtes groupées sélectionnées.

# # #

Voir les articles de David Fitzjarrell