sql >> Databáze >  >> RDS >> Oracle

Pohled na chybu skupiny Oracle

Oracle zavedl novou funkci, seskupení po eliminaci, pro dotazy, kde je seskupit podle sloupce také jedinečným klíčem tabulky. Stejně jako u mnoha nových funkcí ani u této stále nebyly vyřešeny všechny chyby. Problém nastává, když se s hodnotami klíčů manipuluje pomocí volání funkcí. Následující příklad ilustruje problém pomocí tabulky s DATE jako primárním klíčem a extrahováním roku pomocí TO_CHAR nebo EXTRACT.

Tabulka se vytvoří následovně:

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;

Po provedení níže uvedeného dotazu se zobrazí následující výsledky:

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 ‚neví‘, že hodnoty klíče byly zmanipulovány tak, že již nejsou jedinečné, a proto optimalizátor aplikuje eliminaci skupin podle jedinečného klíče s méně než hvězdnými výsledky,

EXTRACT si nevede o nic lépe a vrací stejné výsledky. Toto chování je řízeno parametrem „_optimizer_aggr_groupby_elim“, který je ve výchozím nastavení nastaven na hodnotu true. Jelikož se jedná o skrytý parametr, Oracle jeho nastavení nehlásí ani v zobrazení V$PARAMEter, ani V$SPPARAMETER. Řešením je jednoduše nastavit tento parametr na hodnotu false. Jeho aktivní však může pomoci dalším skupinovým dotazům, kde se s jedinečnými hodnotami klíče nemanipuluje.

Zadejte Oracle 19c, kde je tato funkce částečně opravena:

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


Bohužel EXTRACT je stále přerušen v 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

Je zřejmé, že za předpokladu skutečně jedinečných hodnot klíčů by dotaz po skupinách vytvořil počet 1 pro každý klíč. A jak je zřejmé, Oracle by měl být schopen rozpoznat, kdy hodnoty již nejsou jedinečné, a vyvolat správný mechanismus po skupinách. Zbývá zjistit, zda verze po 19c opraví druhou podmínku a vrátí tak správné výsledky, aniž by bylo nutné tuto funkci vypínat.

To nemusí mít vliv na každou instalaci Oracle novější než 12.1, ale stojí za to vědět o tom, pokud by se ve vybrané skupině podle dotazů začaly objevovat nesprávné výsledky.

# # #

Viz články odDavida Fitzjarrella


  1. Sníží se výkon SQLite, pokud je velikost databáze větší než 2 gigabajty?

  2. Chyba syntaxe tabulky Postgres

  3. Aktualizujte data v databázi MySQL

  4. Jak kombinovat datum z jednoho pole s časem z jiného pole - MS SQL Server