Highload++ Siberia 2019 ізімен — 8 Oracle тапсырмасы

Сәлем!

24-25 маусымда Новосибирск қаласында Highload++ Siberia 2019 конференциясы өтті.Онда біздің жігіттер де болды. есеп беру «Oracle контейнерлік дерекқорлары (CDB/PDB) және оларды бағдарламалық жасақтаманы әзірлеу үшін практикалық пайдалану», біз мәтіндік нұсқасын сәл кейінірек жариялаймыз. Керемет болды, рахмет олегбунин ұйымға, сондай-ақ келгендердің барлығына.

Highload++ Siberia 2019 ізімен — 8 Oracle тапсырмасы
Бұл постта сіз өзіңіздің Oracle біліміңізді тексере алуыңыз үшін стендімізде болған мәселелермен бөліскіміз келеді. Қиманың астында 8 есеп, жауап нұсқалары және түсініктеме берілген.

Келесі сценарийді орындау нәтижесінде біз көретін ең жоғары реттілік мәні қандай?

create sequence s start with 1;
 
select s.currval, s.nextval, s.currval, s.nextval, s.currval
from dual
connect by level <= 5;

  • 1
  • 5
  • 10
  • 25
  • Жоқ, қате болады

жауапOracle құжаттамасына сәйкес (8.1.6-дан алынған):
Жалғыз SQL мәлімдемесінде Oracle ретті әр жолға тек бір рет арттырады. Егер мәлімдеме реттілік үшін NEXTVAL сілтемесіне бірнеше сілтемені қамтыса, Oracle ретті бір рет арттырады және NEXTVAL барлық оқиғалары үшін бірдей мәнді қайтарады. Мәлімдемеде CURRVAL және NEXTVAL екеуіне де сілтемелер болса, Oracle ретті ұлғайтады және мәлімдемедегі ретіне қарамастан CURRVAL және NEXTVAL үшін бірдей мәнді қайтарады.

Осылайша, максималды мән жолдар санына сәйкес болады, яғни 5.

Келесі сценарийді орындау нәтижесінде кестеде қанша жол болады?

create table t(i integer check (i < 5));
 
create procedure p(p_from integer, p_to integer) as
begin
    for i in p_from .. p_to loop
        insert into t values (i);
    end loop;
end;
/
 
exec p(1, 3);
exec p(4, 6);
exec p(7, 9);

  • 0
  • 3
  • 4
  • 5
  • 6
  • 9

жауапOracle құжаттамасына сәйкес (11.2-дан алынған):

Кез келген SQL мәлімдемесін орындамас бұрын, Oracle жасырын сақтау нүктесін белгілейді (сізге қолжетімді емес). Одан кейін мәлімдеме сәтсіз болса, Oracle оны автоматты түрде қайтарады және SQLCA ішіндегі SQLCODE қолданбасына сәйкес қате кодын қайтарады. Мысалы, INSERT операторы қайталанатын мәнді бірегей индекске кірістіру әрекеті арқылы қате тудырса, мәлімдеме кері қайтарылады.

Клиенттен HP компаниясына қоңырау шалу да бір мәлімдеме ретінде қарастырылады және өңделеді. Осылайша, бірінші HP қоңырауы үш жазбаны енгізе отырып, сәтті аяқталды; екінші HP қоңырауы қатемен аяқталады және ол енгізе алған төртінші жазбаны кері қайтарады; үшінші қоңырау сәтсіз аяқталды, және кестеде үш жазба бар.

Келесі сценарийді орындау нәтижесінде кестеде қанша жол болады?

create table t(i integer, constraint i_ch check (i < 3));
 
begin
    insert into t values (1);
    insert into t values (null);
    insert into t values (2);
    insert into t values (null);
    insert into t values (3);
    insert into t values (null);
    insert into t values (4);
    insert into t values (null);
    insert into t values (5);
exception
    when others then
        dbms_output.put_line('Oops!');
end;
/

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

жауапOracle құжаттамасына сәйкес (11.2-дан алынған):

Тексеру шектеуі кестедегі әрбір жол қанағаттандыратын шартты көрсетуге мүмкіндік береді. Шектеуді қанағаттандыру үшін кестедегі әрбір жол шартты TRUE немесе белгісіз (нөлге байланысты) жасауы керек. Oracle белгілі бір жол үшін шектеуді шектеу шартын бағалағанда, шарттағы кез келген баған атаулары сол жолдағы баған мәндеріне сілтеме жасайды.

Осылайша, null мәні тексеруден өтеді, ал анонимді блок 3 мәнін енгізу әрекетіне дейін сәтті орындалады. Осыдан кейін қатені өңдеу блогы ерекше жағдайды жояды, кері қайтару болмайды және кестеде төрт жол қалады 1, null, 2 және қайтадан нөл мәндерімен.

Қандай жұп мәндер блокта бірдей орын алады?

create table t (
    a char(1 char),
    b char(10 char),
    c char(100 char),
    i number(4),
    j number(14),
    k number(24),
    x varchar2(1 char),
    y varchar2(10 char),
    z varchar2(100 char));
 
insert into t (a, b, i, j, x, y)
    values ('Y', 'Вася', 10, 10, 'Д', 'Вася');

  • A және X
  • B және Y
  • C және K
  • C және Z
  • К және З
  • Мен және Дж
  • J және X
  • Барлық тізімделген

жауапМұнда Oracle-да деректердің әртүрлі түрлерін сақтауға арналған құжаттамадан (12.1.0.2) үзінділер берілген.

CHAR деректер түрі
CHAR деректер түрі дерекқор таңбалар жиынындағы тұрақты ұзындықтағы таңбалар жолын көрсетеді. Дерекқорды жасаған кезде дерекқор таңбалар жинағын көрсетесіз. Oracle CHAR бағанында сақталған барлық мәндердің таңдалған ұзындық семантикасындағы өлшем бойынша көрсетілген ұзындыққа ие болуын қамтамасыз етеді. Баған ұзындығынан қысқа мәнді енгізсеңіз, Oracle мәнді баған ұзындығына толтырады.

VARCHAR2 Деректер түрі
VARCHAR2 деректер түрі дерекқор таңбалар жиынындағы айнымалы ұзындықтағы таңбалар жолын көрсетеді. Дерекқорды жасаған кезде дерекқор таңбалар жинағын көрсетесіз. Oracle таңба мәнін VARCHAR2 бағанында дәл сіз көрсеткендей, ешқандай бос толтырусыз сақтайды, егер мән баған ұзындығынан аспаса.

NUMBER деректер түрі
NUMBER деректер түрі нөлді, сондай-ақ абсолютті мәндері 1.0 x 10-130-дан 1.0 x 10126-ға дейінгі оң және теріс тіркелген сандарды сақтайды. Егер мәні абсолютті мәнінен үлкен немесе оған тең арифметикалық өрнекті көрсетсеңіз 1.0 x 10126, содан кейін Oracle қатені қайтарады. Әрбір NUMBER мәні 1-ден 22 байтқа дейін қажет. Осыны ескере отырып, NUMBER(p) белгілі бір сандық деректер мәні үшін байттағы баған өлшемін, мұндағы p - берілген мәннің дәлдігі келесі формула арқылы есептелуі мүмкін: ROUND((ұзындығы(p)+s)/2))+1 Мұндағы сан оң болса s нөлге, ал теріс болса s 1-ге тең.

Сонымен қатар, Null мәндерін сақтау туралы құжаттамадан үзінді алайық.

Нөл – бағандағы мәннің болмауы. Нөлдер жоқ, белгісіз немесе қолданылмайтын деректерді көрсетеді. Нөлдер деректер мәндері бар бағандар арасында болса, дерекқорда сақталады. Бұл жағдайларда олар бағанның ұзындығын (нөл) сақтау үшін 1 байтты қажет етеді. Жолдағы нөлдік мәндер сақтауды қажет етпейді, себебі жаңа жол тақырыбы алдыңғы жолдағы қалған бағандардың бос екенін көрсетеді. Мысалы, кестенің соңғы үш бағанасы нөл болса, онда бұл бағандар үшін деректер сақталмайды.

Осы деректерге сүйене отырып, біз пайымдауды құрастырамыз. Дерекқор AL32UTF8 кодтауын пайдаланады деп есептейміз. Бұл кодтауда орыс әріптері 2 байтты алады.

1) A және X, a 'Y' өрісінің мәні 1 байт, x 'D' өрісінің мәні 2 байт алады
2) B және Y, b ішіндегі «Вася» мән 10 таңбаға дейін бос орындармен толтырылады және 14 байт алады, d ішіндегі «Вася» 8 байт алады.
3) C және K. Екі өрісте де NULL мәні бар, олардан кейін маңызды өрістер бар, сондықтан олар 1 байтты алады.
4) C және Z. Екі өрісте де NULL мәні бар, бірақ Z өрісі кестедегі соңғы, сондықтан ол бос орын алмайды (0 байт). C өрісі 1 байтты алады.
5) K және Z. Алдыңғы жағдайға ұқсас. K өрісіндегі мән 1 байтты алады, Z – 0.
6) I және J. Құжаттамаға сәйкес екі мән де 2 байт алады. Құжаттамадан алынған формуланы пайдаланып ұзындықты есептейміз: round( (1 + 0)/2) +1 = 1 + 1 = 2.
7) J және X. J өрісіндегі мән 2 байт, X өрісіндегі мән 2 байт алады.

Барлығы дұрыс нұсқалар: C және K, I және J, J және X.

T_I индексінің кластерлік факторы шамамен қанша болады?

create table t (i integer);
 
insert into t select rownum from dual connect by level <= 10000;
 
create index t_i on t(i);

  • Ондағанға жуық
  • Жүздегендей
  • Мыңға жуық
  • Ондаған мыңға жуық

жауапOracle құжаттамасына сәйкес (12.1-дан алынған):

B-ағаш индексі үшін индексті кластерлеу факторы индекс мәніне қатысты жолдардың физикалық топтастырылуын өлшейді.

Индексті кластерлеу факторы оңтайландырушыға индексті сканерлеу немесе толық кестені сканерлеу белгілі бір сұраулар үшін тиімдірек екенін шешуге көмектеседі). Төмен кластерлеу коэффициенті тиімді индексті сканерлеуді көрсетеді.

Кестедегі блоктар санына жақын кластерлеу коэффициенті жолдардың индекс кілті арқылы кесте блоктарында физикалық реттелгенін көрсетеді. Егер дерекқор кестені толық қарап шығуды орындаса, онда дерекқор жолдарды индекс кілті бойынша сұрыпталған дискіде сақталатындықтан шығарып алуға бейім болады. Жолдар санына жақын кластерлеу коэффициенті жолдардың индекс кілтіне қатысты дерекқор блоктары бойынша кездейсоқ шашыраңқы екенін көрсетеді. Егер дерекқор толық кестені қарап шығуды орындаса, онда дерекқор осы индекс кілті арқылы кез келген сұрыпталған ретпен жолдарды шығармайды.

Бұл жағдайда деректер өте жақсы сұрыпталған, сондықтан кластерлеу коэффициенті кестеде орналасқан блоктар санына тең немесе оған жақын болады. Стандартты блок өлшемі 8 килобайт үшін бір блокқа мыңға жуық тар сандық мәндер сәйкес келеді деп күтуге болады, сондықтан блоктар саны, нәтижесінде кластерлеу коэффициенті болады. ондағанға жуық.

Келесі сценарий стандартты параметрлері бар кәдімгі дерекқорда қандай N мәндерінде сәтті орындалады?

create table t (
    a varchar2(N char),
    b varchar2(N char),
    c varchar2(N char),
    d varchar2(N char));
 
create index t_i on t (a, b, c, d);

  • 100
  • 200
  • 400
  • 800
  • 1600
  • 3200
  • 6400

жауапOracle құжаттамасына сәйкес (11.2-дан алынған):

Логикалық деректер қорының шектері

тармақ
Лимит түрі
Шекті мән

индекстері
Индекстелген бағанның жалпы өлшемі
Дерекқор блогының көлемінің 75% минус кейбір үстеме шығындар

Осылайша, индекстелген бағандардың жалпы өлшемі 6Кб-тан аспауы керек. Әрі қарай не болатыны таңдалған негізгі кодтауға байланысты. AL32UTF8 кодтауы үшін бір таңба максимум 4 байтты алуы мүмкін, сондықтан ең нашар жағдайда 6-ге жуық таңба 1500 килобайтқа сәйкес келеді. Сондықтан Oracle индексті N = 400 (ең нашар жағдайда кілт ұзындығы 1600 таңба * 4 байт + қатар ұзындығы болған кезде) жасауға тыйым салады. N = 200 (немесе одан аз) индексті жасау қиындықсыз жұмыс істейді.

APPEND кеңесі бар INSERT операторы деректерді тікелей режимде жүктеуге арналған. Ол триггер ілулі тұрған кестеге қолданылса не болады?

  • Деректер тікелей режимде жүктеледі, триггер күткендей жұмыс істейді
  • Деректер тікелей режимде жүктеледі, бірақ триггер орындалмайды
  • Деректер әдеттегі режимде жүктеледі, триггер қажетінше жұмыс істейді
  • Деректер әдеттегі режимде жүктеледі, бірақ триггер орындалмайды
  • Деректер жүктелмейді, қате жазылады

жауапНегізінен бұл логика мәселесі. Дұрыс жауапты табу үшін мен келесі дәлелдеу үлгісін ұсынар едім:

  1. Тікелей режимде кірістіру жоғары жылдамдықты қамтамасыз ететін SQL қозғалтқышын айналып өтіп, деректер блогын тікелей қалыптастыру арқылы жүзеге асырылады. Осылайша, триггердің орындалуын қамтамасыз ету өте қиын, тіпті мүмкін емес және мұның еш мәні жоқ, өйткені ол әлі де кірістіруді түбегейлі баяулатады.
  2. Триггерді орындамау, егер кестедегі деректер бірдей болса, жалпы деректер қорының күйі (басқа кестелер) осы деректер енгізілген режимге байланысты болады. Бұл деректердің тұтастығын бұзады және оны өндірісте шешім ретінде қолдану мүмкін емес.
  3. Сұралған әрекетті орындау мүмкін еместігі әдетте қате ретінде қарастырылады. Бірақ бұл жерде APPEND – бұл тұспал екенін есте ұстағанымыз жөн, ал кеңестердің жалпы логикасы – мүмкін болса, олар ескеріледі, ал олай болмаса, оператор кеңесті есепке алмай орындалады.

Сондықтан күтілетін жауап деректер қалыпты (SQL) режимінде жүктеледі, триггер іске қосылады.

Oracle құжаттамасына сәйкес (8.04-дан алынған):

Шектеулерді бұзу мәлімдеменің әдеттегі кірістіру жолын пайдаланып, ескертусіз немесе қате туралы хабарсыз сериялық орындалуына әкеледі. Ерекшелік - қате туралы хабарларды тудыруы мүмкін транзакцияда бір кестеге бірнеше рет қатынасатын мәлімдемелерге шектеу.
Мысалы, егер кестеде триггерлер немесе сілтеме тұтастығы болса, тікелей жүктелетін INSERT (сериялық немесе параллель), сондай-ақ, егер бар болса, PARALLEL кеңесін немесе сөйлемді пайдалануға әрекет жасағанда APPEND кеңесі еленбейді.

Келесі сценарий орындалғанда не болады?

create table t(i integer not null primary key, j integer references t);
 
create trigger t_a_i after insert on t for each row
declare
    pragma autonomous_transaction;
begin
    insert into t values (:new.i + 1, :new.i);
    commit;
end;
/
 
insert into t values (1, null);

  • Сәтті орындалу
  • Синтаксистік қатеге байланысты сәтсіздік
  • Қате: автономды транзакция жарамсыз
  • Қоңырауларды орналастырудың максималды шегінен асып кетуге қатысты қате
  • Сыртқы кілтті бұзу қатесі
  • Құлыптарға қатысты қате

жауапКесте мен триггер өте дұрыс жасалған және бұл операция ақауларға әкелмеуі керек. Триггердегі автономды транзакцияларға да рұқсат етіледі, әйтпесе, мысалы, тіркеу мүмкін болмайды.

Бірінші жолды енгізгеннен кейін триггердің сәтті іске қосылуы екінші жолдың енгізілуіне себеп болады, бұл триггердің қайта іске қосылуына, үшінші жолдың кірістірілуіне және т.б. шақырулардың максималды кірістіру шегінен асып кетуіне байланысты мәлімдеме сәтсіз аяқталмайынша жалғасады. Дегенмен, тағы бір нәзік нүкте ойнайды. Триггер орындалған кезде бірінші енгізілген жазба үшін міндеттеме әлі аяқталмаған. Демек, автономды транзакцияда іске қосылған триггер әлі орындалмаған жазбаға сыртқы кілтке сілтеме жасайтын жолды кестеге кірістіруге тырысады. Бұл күтуге әкеледі (автономды транзакция негізгі транзакцияның деректерді кірістіре алатынын көру үшін орындауын күтеді) және сонымен бірге негізгі транзакция триггерден кейін автономды транзакцияның жұмысын жалғастыруды күтеді. Тығырықтау орын алады және нәтижесінде құлыптарға байланысты себептерге байланысты автономды транзакция тоқтатылады..

Сауалнамаға тек тіркелген пайдаланушылар қатыса алады. Кіру, өтінемін.

Бұл қиын болды ма?

  • Екі саусақтай мен бірден бәрін дұрыс шештім.

  • Шынымен емес, мен бір-екі сұрақ бойынша қателесіппін.

  • Мен оның жартысын дұрыс шештім.

  • Мен жауапты екі рет таптым!

  • Мен түсініктемелерде жазамын

14 пайдаланушы дауыс берді. 10 пайдаланушы қалыс қалды.

Ақпарат көзі: www.habr.com

пікір қалдыру