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