Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Uma olhada no bug do Oracle Group-by


A Oracle introduziu um novo recurso, agrupar por eliminação, para consultas em que o agrupamento por coluna também é a chave exclusiva da tabela. Tal como acontece com muitos novos recursos, este ainda não teve todos os problemas resolvidos. O problema surge quando os valores de chave são manipulados com chamadas de função. O exemplo a seguir ilustrará o problema usando uma tabela com DATE como chave primária e extraindo o ano é extraído usando TO_CHAR ou EXTRACT.

Uma tabela é criada da seguinte forma:
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;


Quando a consulta mostrada abaixo é executada, ela produz os seguintes resultados:
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


A Oracle não "sabe" que os valores de chave foram manipulados para que não sejam mais exclusivos, portanto, o otimizador aplica a eliminação de grupo por chave única com resultados menos que estelares,

EXTRACT não é melhor, retornando os mesmos resultados. Esse comportamento é controlado pelo parâmetro “_optimizer_aggr_groupby_elim”, que é definido como true por padrão. Por ser um parâmetro oculto, sua configuração não é informada pelo Oracle em nenhuma das visualizações V$PARAMEter ou V$SPPARAMETER. A solução alternativa é simplesmente definir esse parâmetro como false. No entanto, tê-lo ativo pode ajudar outras consultas agrupadas em que os valores de chave exclusivos não são manipulados.

Digite Oracle 19c, onde esta funcionalidade é parcialmente corrigida:
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



Infelizmente EXTRACT ainda está quebrado em 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

Obviamente, dados valores de chave verdadeiramente exclusivos, uma consulta agrupar por produziria uma contagem de 1 para cada chave. E, igualmente óbvio, o Oracle deve ser capaz de reconhecer quando os valores não são mais exclusivos e invocar o mecanismo group-by adequado. Resta saber se as versões posteriores a 19c corrigirão a segunda condição e, assim, retornarão resultados corretos sem precisar desativar esse recurso.

Isso pode não afetar todas as instalações do Oracle mais recentes que 12.1, mas vale a pena saber se resultados errados começarem a aparecer em consultas de grupo selecionadas.

# # #

Veja artigos de David Fitzjarrell