„Highload++ Siberia 2019“ pėdomis – 8 užduotys „Oracle“

Sveiki!

Birželio 24-25 dienomis Novosibirske vyko konferencija Highload++ Siberia 2019. Ten buvo ir mūsų vaikinai. ataskaita „Oracle konteinerių duomenų bazės (CDB/PDB) ir jų praktinis panaudojimas kuriant programinę įrangą“, tekstinę versiją publikuosime kiek vėliau. Buvo šaunu, ačiū olegbuninas organizacijai, taip pat visiems atėjusiems.

„Highload++ Siberia 2019“ pėdomis – 8 užduotys „Oracle“
Šiame įraše norėtume pasidalinti su jumis problemomis, su kuriomis susidūrėme mūsų stende, kad galėtumėte pasitikrinti savo Oracle žinias. Po pjūviu yra 8 problemos, atsakymų variantai ir paaiškinimas.

Kokia yra didžiausia sekos reikšmė, kurią matysime vykdydami šį scenarijų?

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
  • Ne, bus klaida

AtsakytiPagal „Oracle“ dokumentus (cituota iš 8.1.6):
Viename SQL sakinyje „Oracle“ seką padidins tik vieną kartą eilutėje. Jei sakinyje yra daugiau nei viena sekos nuoroda į NEXTVAL, „Oracle“ vieną kartą padidina seką ir grąžina tą pačią reikšmę visiems NEXTVAL atvejams. Jei sakinyje yra nuorodų į CURRVAL ir NEXTVAL, „Oracle“ padidina seką ir grąžina tą pačią reikšmę tiek CURRVAL, tiek NEXTVAL, nepaisant jų eilės sakinyje.

tokiu būdu, didžiausia vertė atitiks eilučių skaičių, tai yra 5.

Kiek eilučių bus lentelėje paleidus šį scenarijų?

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

AtsakytiPagal „Oracle“ dokumentus (cituota iš 11.2):

Prieš vykdydama bet kokį SQL sakinį, „Oracle“ pažymi numanomą išsaugojimo tašką (jūs nepasiekiamas). Tada, jei teiginys nepavyksta, „Oracle“ automatiškai grąžina jį atgal ir grąžina taikomą klaidos kodą į SQLCODE SQLCA. Pavyzdžiui, jei INSERT sakinys sukelia klaidą bandant įterpti pasikartojančią reikšmę į unikalų indeksą, sakinys atšaukiamas.

Kliento skambinimas HP taip pat laikomas vienu pareiškimu ir apdorojamas. Taigi pirmasis HP skambutis sėkmingai užbaigiamas, įterpus tris įrašus; antrasis HP skambutis baigiasi klaida ir atšaukiamas ketvirtas įrašas, kurį pavyko įterpti; trečias skambutis nepavyksta, ir lentelėje yra trys įrašai.

Kiek eilučių bus lentelėje paleidus šį scenarijų?

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

AtsakytiPagal „Oracle“ dokumentus (cituota iš 11.2):

Patikrinimo apribojimas leidžia nurodyti sąlygą, kurią turi atitikti kiekviena lentelės eilutė. Kad būtų įvykdytas apribojimas, kiekvienoje lentelės eilutėje sąlyga turi būti TRUE arba nežinoma (dėl nulio). Kai „Oracle“ įvertina tam tikros eilutės tikrinimo apribojimo sąlygą, visi sąlygos stulpelių pavadinimai nurodo tos eilutės stulpelių reikšmes.

Taigi, reikšmė null praeis patikrinimą, o anoniminis blokas bus sėkmingai vykdomas tol, kol bus bandoma įterpti reikšmę 3. Po to klaidų apdorojimo blokas išvalys išimtį, atšaukimas neįvyks ir lentelėje liks keturios eilutės su reikšmėmis 1, null, 2 ir vėl null.

Kurios verčių poros bloke užims tiek pat vietos?

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 ir X
  • B ir Y
  • C ir K
  • C ir Z
  • K ir Z
  • Aš ir J
  • J ir X
  • Visi išvardyti

AtsakytiČia pateikiamos ištraukos iš dokumentacijos (12.1.0.2) apie įvairių tipų duomenų saugojimą „Oracle“.

CHAR duomenų tipas
CHAR duomenų tipas nurodo fiksuoto ilgio simbolių eilutę duomenų bazės simbolių rinkinyje. Duomenų bazės simbolių rinkinį nurodote kurdami duomenų bazę. „Oracle“ užtikrina, kad visos CHAR stulpelyje saugomos reikšmės turi ilgį, nurodytą pagal dydį pasirinktoje ilgio semantikoje. Jei įterpiate reikšmę, kuri yra trumpesnė už stulpelio ilgį, tada „Oracle“ užpildo reikšmę į stulpelio ilgį.

VARCHAR2 duomenų tipas
VARCHAR2 duomenų tipas nurodo kintamo ilgio simbolių eilutę duomenų bazės simbolių rinkinyje. Duomenų bazės simbolių rinkinį nurodote kurdami duomenų bazę. „Oracle“ išsaugo simbolio reikšmę VARCHAR2 stulpelyje tiksliai taip, kaip ją nurodote, be jokio tuščio užpildymo, jei reikšmė neviršija stulpelio ilgio.

NUMBER duomenų tipas
Duomenų tipas NUMBER saugo nulį, taip pat teigiamus ir neigiamus fiksuotus skaičius, kurių absoliučios reikšmės yra nuo 1.0 x 10-130 iki 1.0 x 10126, bet neįskaitant. Jei nurodote aritmetinę išraišką, kurios reikšmė yra didesnė arba lygi 1.0 x 10126, tada Oracle grąžina klaidą. Kiekvienai NUMBER vertei reikia nuo 1 iki 22 baitų. Atsižvelgiant į tai, konkrečios skaitmeninės duomenų reikšmės NUMBER(p) stulpelio dydis baitais, kur p yra nurodytos vertės tikslumas, gali būti apskaičiuojamas naudojant šią formulę: RANDAS((ilgis(p)+s)/2))+1 kur s lygus nuliui, jei skaičius yra teigiamas, ir s lygus 1, jei skaičius yra neigiamas.

Be to, paimkime ištrauką iš dokumentacijos apie Null verčių saugojimą.

Nulis yra vertės nebuvimas stulpelyje. Nuliai nurodo trūkstamus, nežinomus arba netinkamus duomenis. Nuliai saugomi duomenų bazėje, jei jie patenka tarp stulpelių su duomenų reikšmėmis. Tokiais atvejais jiems reikia 1 baito, kad būtų išsaugotas stulpelio ilgis (nulis). Nuliniams eilutės stulpams nereikia vietos, nes nauja eilutės antraštė rodo, kad likę ankstesnės eilutės stulpeliai yra nuliniai. Pavyzdžiui, jei paskutiniai trys lentelės stulpeliai yra nuliniai, šių stulpelių duomenys nesaugomi.

Remdamiesi šiais duomenimis, mes sukuriame samprotavimus. Darome prielaidą, kad duomenų bazėje naudojama AL32UTF8 koduotė. Šioje koduotėje rusiškos raidės užims 2 baitus.

1) A ir X, lauko a reikšmė „Y“ užima 1 baitą, lauko x reikšmė „D“ užima 2 baitus
2) B ir Y, „Vasya“ b reikšmė bus užpildyta tarpais iki 10 simbolių ir užims 14 baitų, „Vasya“ d užims 8 baitus.
3) C ir K. Abu laukai turi reikšmę NULL, po jų yra reikšmingi laukai, todėl jie užima 1 baitą.
4) C ir Z. Abu laukeliai turi reikšmę NULL, bet laukas Z yra paskutinis lentelėje, todėl neužima vietos (0 baitų). C laukas užima 1 baitą.
5) K ir Z. Panašus į ankstesnį atvejį. K lauke esanti reikšmė užima 1 baitą, Z – 0.
6) I ir J. Remiantis dokumentais, abi vertės užims 2 baitus. Ilgį apskaičiuojame pagal formulę, paimtą iš dokumentacijos: apvalus( (1 + 0)/2) +1 = 1 + 1 = 2.
7) J ir X. Reikšmė lauke J bus 2 baitai, reikšmė X lauke užims 2 baitus.

Iš viso teisingos parinktys yra: C ir K, I ir J, J ir X.

Koks apytiksliai bus T_I indekso klasterizacijos koeficientas?

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

  • Apie dešimtis
  • Apie šimtus
  • Apie tūkstančius
  • Apie dešimtis tūkstančių

AtsakytiPagal „Oracle“ dokumentus (cituota iš 12.1):

B-medžio indeksui indekso grupavimo veiksnys matuoja fizinę eilučių grupavimą indekso vertės atžvilgiu.

Indekso grupavimo veiksnys padeda optimizuotojui nuspręsti, ar indekso nuskaitymas ar visos lentelės nuskaitymas yra veiksmingesnis tam tikroms užklausoms). Žemas klasterizacijos koeficientas rodo efektyvų indekso nuskaitymą.

Klasterizacijos koeficientas, artimas blokų skaičiui lentelėje, rodo, kad eilutės lentelės blokuose yra fiziškai sutvarkytos pagal indekso raktą. Jei duomenų bazė atlieka visą lentelės nuskaitymą, duomenų bazė linkusi nuskaityti eilutes, nes jos yra saugomos diske, surūšiuotos pagal indekso raktą. Klasterizacijos koeficientas, artimas eilučių skaičiui, rodo, kad eilutės yra atsitiktinai išsklaidytos duomenų bazės blokuose indekso rakto atžvilgiu. Jei duomenų bazė atlieka visą lentelės nuskaitymą, duomenų bazė nenuskaitys eilučių jokia rūšiavimo tvarka pagal šį indekso raktą.

Šiuo atveju duomenys yra idealiai surūšiuoti, todėl klasterizacijos koeficientas bus lygus arba artimas užimtų blokų skaičiui lentelėje. Jei standartinis bloko dydis yra 8 kilobaitai, galite tikėtis, kad į vieną bloką tilps apie tūkstantis siaurų skaičių reikšmių, taigi blokų skaičius ir dėl to klasterizacijos koeficientas bus apie dešimtis.

Kokiomis N reikšmėmis šis scenarijus bus sėkmingai vykdomas įprastoje duomenų bazėje su standartiniais parametrais?

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

AtsakytiPagal „Oracle“ dokumentus (cituota iš 11.2):

Loginės duomenų bazės ribos

Punktas
Limito tipas
Ribinė vertė

Indeksai
Bendras indeksuoto stulpelio dydis
75% duomenų bazės bloko dydžio, atėmus šiek tiek pridėtinių išlaidų

Taigi bendras indeksuotų stulpelių dydis neturėtų viršyti 6 Kb. Kas nutiks toliau, priklauso nuo pasirinktos pagrindinės koduotės. Naudojant AL32UTF8 koduotę, vienas simbolis gali užimti daugiausiai 4 baitus, todėl blogiausiu atveju apie 6 simbolių tilps į 1500 kilobaitus. Todėl „Oracle“ neleis indekso kūrimo, kai N = 400 (kai blogiausiu atveju rakto ilgis yra 1600 simbolių * 4 baitai + eilutės ilgis), o kai N = 200 (ar mažiau) indekso kūrimas veiks be problemų.

INSERT operatorius su užuomina APPEND yra skirtas duomenims įkelti tiesioginiu režimu. Kas atsitiks, jei jis bus pritaikytas prie stalo, ant kurio kabo gaidukas?

  • Duomenys bus įkeliami tiesioginiu režimu, trigeris veiks kaip tikėtasi
  • Duomenys bus įkeliami tiesioginiu režimu, tačiau paleidiklis nebus vykdomas
  • Duomenys bus įkeliami įprastu režimu, trigeris veiks kaip priklauso
  • Duomenys bus įkeliami įprastu režimu, tačiau paleidiklis nebus vykdomas
  • Duomenys nebus įkeliami, bus įrašyta klaida

AtsakytiIš esmės tai daugiau logikos klausimas. Norint rasti teisingą atsakymą, siūlyčiau tokį samprotavimo modelį:

  1. Įterpimas tiesioginiu režimu atliekamas tiesiogiai formuojant duomenų bloką, apeinant SQL variklį, kuris užtikrina didelį greitį. Taigi užtikrinti, kad paleidiklis būtų įvykdytas, yra labai sunku, jei ne neįmanoma, ir tai nėra prasmės, nes tai vis tiek radikaliai sulėtins įterpimą.
  2. Nepavykus vykdyti trigerio, jei duomenys lentelėje yra vienodi, visos duomenų bazės (kitų lentelių) būsena priklausys nuo režimo, kuriuo šie duomenys buvo įterpti. Tai akivaizdžiai sunaikins duomenų vientisumą ir negali būti taikomas kaip sprendimas gamyboje.
  3. Nesugebėjimas atlikti prašomos operacijos paprastai traktuojamas kaip klaida. Bet čia turėtume prisiminti, kad APPEND yra užuomina, o bendra užuominų logika yra tokia, kad jei įmanoma, į jas atsižvelgiama, bet jei ne, operatorius vykdomas neatsižvelgiant į užuominą.

Taigi laukiamas atsakymas duomenys bus įkeliami įprastu (SQL) režimu, suveiks trigeris.

Pagal „Oracle“ dokumentus (cituota iš 8.04):

Pažeidus apribojimus, sakinys bus vykdomas nuosekliai, naudojant įprastą įterpimo kelią, be įspėjimų ar klaidų pranešimų. Išimtis yra apribojimas teiginiams prieiti prie tos pačios lentelės daugiau nei vieną kartą per operaciją, o tai gali sukelti klaidų pranešimus.
Pavyzdžiui, jei lentelėje yra trigerių arba nuorodos vientisumo, tada APPEND užuomina bus nepaisoma, kai bandysite naudoti tiesioginės įkrovos INSERT (nuosekliąją arba lygiagrečiąją), taip pat PARALLEL užuominą ar sąlygą, jei tokia yra.

Kas atsitiks, kai bus vykdomas šis scenarijus?

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);

  • Sėkmingas užbaigimas
  • Gedimas dėl sintaksės klaidos
  • Klaida: autonominis sandoris negalioja
  • Klaida, susijusi su maksimalaus skambučių įdėjimo viršijimu
  • Užsienio rakto pažeidimo klaida
  • Su spynomis susijusi klaida

AtsakytiLentelė ir trigeris sukurti gana teisingai, todėl ši operacija neturėtų sukelti problemų. Taip pat leidžiamos savarankiškos operacijos trigeryje, nes kitaip, pavyzdžiui, nebūtų įmanoma registruoti.

Įterpus pirmąją eilutę, sėkmingai suaktyvinus aktyviklį, būtų įterpta antroji eilutė, dėl kurios aktyviklis vėl suaktyvintų, įterptų trečią eilutę ir taip toliau, kol pareiškimas nepavyko dėl maksimalaus iškvietimų įdėjimo. Tačiau atsiranda dar vienas subtilus dalykas. Tuo metu, kai vykdomas trigeris, pirmojo įterpto įrašo įsipareigojimas dar nebuvo baigtas. Todėl aktyviklis, veikiantis autonominėje operacijoje, bando į lentelę įterpti eilutę, nurodančią užsienio raktą į įrašą, kuris dar neįparduotas. Dėl to laukiama (autonominė transakcija laukia, kol pagrindinė transakcija įsipareigos, kad pamatytų, ar ji gali įterpti duomenis), ir tuo pačiu metu pagrindinė operacija laukia, kol autonominė transakcija toliau veiks po trigerio. Atsiranda aklavietė ir dėl to autonominė operacija atšaukiama dėl priežasčių, susijusių su užraktais.

Apklausoje gali dalyvauti tik registruoti vartotojai. Prisijungti, Prašau.

Ar buvo sunku?

  • Kaip du pirštai iškart viską nusprendžiau teisingai.

  • Tikrai ne, aš klydau keliais klausimais.

  • Pusę išsprendžiau teisingai.

  • Du kartus atspėjau atsakymą!

  • Komentaruose parašysiu

Balsavo 14 vartotojų. 10 vartotojai susilaikė.

Šaltinis: www.habr.com

Добавить комментарий