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, но си струва да знаете за това, ако в избраната група по заявки започнат да се появяват грешни резултати.
# # #
Вижте статии отДейвид Фицярел