Oracle
 sql >> база данни >  >> RDS >> Oracle

Поглед към грешката на Oracle Group-by

Oracle въведе нова функция, група по елиминиране, за заявки, където групата по колона също е уникалният ключ на таблицата. Както при много нови функции, и тази все още не е разрешила всички пречупвания. Проблемът възниква, когато ключовите стойности се манипулират с извиквания на функции. Следният пример ще илюстрира проблема чрез използване на таблица с DATE като първичен ключ и чрез извличане на годината се извлича с помощта на TO_CHAR или EXTRACT.

Създава се таблица, както следва:

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;

Когато заявката, показана по-долу, се изпълни, тя дава следните резултати:

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 не „знае“, че ключовите стойности са били манипулирани, така че вече да не са уникални, поради което оптимизаторът прилага групово елиминиране, базирано на уникален ключ, с по-малко от звездни резултати,

EXTRACT не работи по-добре, връщайки същите резултати. Това поведение се контролира от параметъра „_optimizer_aggr_groupby_elim“, който е настроен на true по подразбиране. Тъй като това е скрит параметър, неговата настройка не се отчита от Oracle в нито един от изгледите V$PARAMEter или V$SPARAMETER. Заобикалянето е просто да зададете този параметър на false. Активирането му обаче може да помогне на други групови заявки, при които стойностите на уникалния ключ не се манипулират.

Въведете Oracle 19c, където тази функционалност е частично фиксирана:

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


За съжаление EXTRACT все още е разбит в 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

Очевидно при дадени наистина уникални стойности на ключ, заявка група по ще доведе до брой 1 за всеки ключ. И също толкова очевидно, Oracle трябва да може да разпознава кога стойностите вече не са уникални и да извиква правилния механизъм за група по. Остава да видим дали версии след 19c ще коригират второто условие и по този начин ще върнат правилни резултати, без да се налага да изключват тази функция.

Това може да не се отрази на всяка инсталация на Oracle по-нова от 12.1, но си струва да знаете за това, ако в избраната група по заявки започнат да се появяват грешни резултати.

# # #

Вижте статии отДейвид Фицярел


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Функция CURRENT_DATE в Oracle

  2. Oracle ODP.Net и EF CodeFirst - Грешка при запазване на промените

  3. Как да изпълним процедура с процедурата DBMS_SCHEDULER.CREATE_JOB

  4. Как да повишите производителността за групови INSERT към ODBC свързани таблици в Access?

  5. премахване на милисекунди от поле на оракул tmstmp